<?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[Sameer’s Dev Log]]></title><description><![CDATA[Developer blog - notes, experiments, and learnings across tech.]]></description><link>https://blog.sameerbhagtani.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 24 Apr 2026 08:36:12 GMT</lastBuildDate><atom:link href="https://blog.sameerbhagtani.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Behind the Root: Linux Filesystem Demystified]]></title><description><![CDATA[Introduction
If you ever installed and tried out Linux after seeing a cool hacking sequence in a sci-fi movie, you know that opening it feels like stepping into a strange city with many roads named /b]]></description><link>https://blog.sameerbhagtani.dev/linux-filesystem-demystified</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/linux-filesystem-demystified</guid><category><![CDATA[Linux]]></category><category><![CDATA[networking]]></category><category><![CDATA[Security]]></category><category><![CDATA[dns]]></category><category><![CDATA[file system]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Wed, 22 Apr 2026 17:08:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/4efcb3ae-fc32-48a7-b846-7b2a4f2e55a4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>If you ever installed and tried out Linux after seeing a cool hacking sequence in a sci-fi movie, you know that opening it feels like stepping into a strange city with many roads named <code>/bin</code>, <code>/home</code> and <code>/tmp</code>. As beginners, we tend to ignore them and go on with our Linux usage by simply remembering the most commonly used commands.</p>
<p>While that approach works initially, it is good to take a step back and understand the Linux Filesystem properly. As "good" developers, who actually get their code out of <code>localhost</code>, we need to understand Linux to its core, because that is what drives the majority of web servers.</p>
<p>In this blog post, I have broken down the philosophy behind the Linux Filesystem, what all those randomly named directories actually do, and some cool insights along the way.</p>
<hr />
<h2>The Core Philosophy: Everything is a File</h2>
<p>A fascinating thing about Linux is that everything, literally everything in Linux, is represented as a file in the Filesystem. This includes not just documents, but devices, processes, sockets, and even hardware!</p>
<p>To digest this idea properly, we need to change our perspective on what a "file" actually means. We usually think of a "file" as a document on our system. In Linux though, a "file" is just a stream of bytes with a path. That's it. Anything that can be read from or written to fits that definition.</p>
<p>Let's look at some examples of files as per this new definition:</p>
<table>
<thead>
<tr>
<th>Path</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>/home/user/gta-cheat-codes.txt</code></td>
<td>Just a simple file that the user has created</td>
</tr>
<tr>
<td><code>/dev/input/...</code></td>
<td>Your input devices like keyboard, mouse</td>
</tr>
<tr>
<td><code>/dev/sda</code></td>
<td>Literally your hard drive</td>
</tr>
<tr>
<td><code>/proc/1234</code></td>
<td>A running process</td>
</tr>
</tbody></table>
<p>Since everything is a file, you can do powerful things like pipe data between programs, redirect output, and chain tools together. This is the exact reason why the Linux terminal is so powerful.</p>
<p>This core philosophy is what gives the Linux Filesystem its structure.</p>
<hr />
<h2>Filesystem Hierarchy Standard (FHS)</h2>
<p>Before we dive deep into the directory structure, I want to mention that the Linux Filesystem isn't a random arrangement of resources in a tree-like structure. There is a specification called the "Filesystem Hierarchy Standard" that defines the directory structure and contents in Linux and other Unix-like operating systems. It is maintained by the Linux Foundation.</p>
<h3>The Problem it Solves</h3>
<p>Before FHS, different Unix distributions placed files wherever they wanted. A config file might live in <code>/etc</code> on one system and <code>/usr/config</code> on another. This made it a nightmare to:</p>
<ul>
<li><p>Write portable software</p>
</li>
<li><p>Move between distributions</p>
</li>
<li><p>Predict where anything lives</p>
</li>
</ul>
<p>FHS serves as a guideline, which most major distros like Debian, Fedora and Arch follow closely to maintain uniformity and predictability.</p>
<hr />
<h2>The Root Directory</h2>
<p>The root directory is the top of the entire filesystem tree in Linux. It is represented by <code>/</code>. The reason it is called the "root" is because there is nothing above it. You can go back as much as you want but never beyond the "root".</p>
<p>If you're from the Windows ecosystem, you can think of this as your <code>C:\</code>. Everything, including files, devices, processes, and external drives, all mount within this same tree.</p>
<p>We can run the <code>ls</code> command at the root of our linux system, and would get the following directories:</p>
<pre><code class="language-plaintext">/
├── bin     -&gt; Essential command binaries
├── boot    -&gt; Kernel and bootloader files
├── dev     -&gt; Device files to interface with hardware
├── etc     -&gt; Text-based configuration files
├── home    -&gt; Personal directories for each user
├── lib     -&gt; Shared library files used by binaries
├── media   -&gt; Mount point for removable media (USBs, CDs)
├── mnt     -&gt; Temporary mount point for filesystems
├── opt     -&gt; Optional, add-on software packages
├── proc    -&gt; Virtual filesystem tracking running processes
├── root    -&gt; Home directory for the root user
├── run     -&gt; Runtime data for processes since last boot
├── sbin    -&gt; System binaries for administrative use
├── srv     -&gt; Data served by the system (FTP, HTTP, etc.)
├── sys     -&gt; Virtual filesystem exposing kernel internals
├── tmp     -&gt; Temporary files, cleared on reboot
├── usr     -&gt; Secondary hierarchy for user installed software
└── var     -&gt; Variable data like logs, caches and spools
</code></pre>
<hr />
<h2><code>/etc</code>: System Configuration Hub</h2>
<p>I personally like to refer to it as the "Configuration Hub" of the entire system. The reason is that every major program, service, and system behavior has its config file here.</p>
<p>Moreover, it's all just plain text. This simple design choice makes configurations readable and easily editable. This is what makes Linux so customizable.</p>
<pre><code class="language-plaintext">/etc
├── hostname       -&gt; The machine's host name
├── hosts          -&gt; Local DNS overrides
├── nsswitch.conf  -&gt; Controls the order of lookups
├── resolv.conf    -&gt; DNS server configuration
├── network/       -&gt; Network interface configuration (Debian)
├── netplan/       -&gt; Network interface configuration (Ubuntu)
├── passwd         -&gt; User account information
├── shadow         -&gt; Hashed user passwords
├── group          -&gt; Group memberships
├── sudoers        -&gt; Controls who can run commands as root
├── environment    -&gt; System-wide environment variables
├── profile        -&gt; Shell environment on login
└── systemd/
    └── system/    -&gt; Service unit files
</code></pre>
<hr />
<h2>Password Storage</h2>
<p>Most people assume passwords are stored somewhere as plain text or in one file. Linux is much smarter than that. It splits user information across multiple files with specific jobs.</p>
<h3><code>/etc/passwd</code></h3>
<p>Despite the name, this file does not store passwords anymore. It stores user account information. Every line is one user, and it looks like this:</p>
<pre><code class="language-plaintext">root:x:0:0:root:/root:/bin/bash
sameer:x:1000:1000:Sameer Bhagtani:/home/sameer:/bin/bash
</code></pre>
<p>Each colon-separated field means:</p>
<ol>
<li><p>Username</p>
</li>
<li><p>Password field: just an <code>x</code>, meaning "go look in <code>/etc/shadow</code>"</p>
</li>
<li><p>UID: User ID, a unique number for the user</p>
</li>
<li><p>GID: Group ID, the user's primary group</p>
</li>
<li><p>GECOS: Full name or description</p>
</li>
<li><p>Home directory</p>
</li>
<li><p>Default shell</p>
</li>
</ol>
<h3><code>/etc/shadow</code></h3>
<p>This is where the actual passwords live. Linux doesn't store them in plain text format. Instead, it hashes the password for security.</p>
<p>This file is only readable by root. A line looks like:</p>
<pre><code class="language-plaintext">root:\(y\)j9T\(randomsalt\)hashedpasswordstring:20384::::::
</code></pre>
<p>Each colon-separated field means:</p>
<ol>
<li><p>Username</p>
</li>
<li><p>Hashed password</p>
</li>
<li><p>Last password change: days since Jan 1, 1970</p>
</li>
<li><p>Minimum password age: days before password can be changed</p>
</li>
<li><p>Maximum password age: days before password must be changed</p>
</li>
<li><p>Warning period: days before expiry to warn the user</p>
</li>
<li><p>Remaining fields: inactivity period, expiry date, reserved</p>
</li>
</ol>
<hr />
<h2>Groups</h2>
<p>A group in Linux is simply a collection of users. Linux uses groups to manage permissions at scale. Instead of setting permissions for each user individually, you assign permissions to a group and add users to it.</p>
<p>For example, you have 5 developers who all need access to <code>/var/www/</code>. Instead of giving each of them individual access, you create a <code>www-data</code> group, give the group access to that folder, and add all 5 users to it.</p>
<p>All this information is stored in <code>/etc/group</code>, where a line looks like:</p>
<pre><code class="language-plaintext">network:x:27:user1,user2
</code></pre>
<p>Each colon-separated field means:</p>
<ol>
<li><p>Group name</p>
</li>
<li><p>Password: almost always x or empty, group passwords are rarely used</p>
</li>
<li><p>GID: Group ID</p>
</li>
<li><p>Members: comma-separated list of users in the group</p>
</li>
</ol>
<h3>Default Groups</h3>
<p>Following are the meanings of some of the default groups in Linux:</p>
<table>
<thead>
<tr>
<th>Group</th>
<th>What it gives you access to</th>
</tr>
</thead>
<tbody><tr>
<td><code>wheel</code></td>
<td><code>sudo</code> privileges</td>
</tr>
<tr>
<td><code>audio</code></td>
<td>Sound devices</td>
</tr>
<tr>
<td><code>video</code></td>
<td>GPU and display devices</td>
</tr>
<tr>
<td><code>storage</code></td>
<td>Mounting drives and storage devices</td>
</tr>
<tr>
<td><code>network</code></td>
<td>Managing network connections</td>
</tr>
</tbody></table>
<hr />
<h2>DNS Configuration</h2>
<p>When you type <code>google.com</code> in your browser, your system needs to figure out the IP address behind it. This process is called DNS resolution. I have written a blog post about DNS resolution in depth, in case you're interested:</p>
<p><a href="https://blog.sameerbhagtani.dev/dns-resolution-explained">https://blog.sameerbhagtani.dev/dns-resolution-explained</a></p>
<p>Linux handles this in a specific order, and /etc controls that entire pipeline.</p>
<h3><code>/etc/hosts</code></h3>
<p>This is checked before any DNS server is even contacted. It's a simple static lookup table that maps hostnames to IP addresses manually. It looks like:</p>
<pre><code class="language-plaintext">127.0.0.1       localhost
192.168.1.10    myserver.local
</code></pre>
<p>So if you add <code>google.com</code> here pointing to some other IP, your system will use that and never bother asking a DNS server. This is why it's called a local DNS override. Developers use this all the time to point a domain to their local machine for testing.</p>
<h3><code>/etc/resolv.conf</code></h3>
<p>This is where your DNS servers are defined. When <code>/etc/hosts</code> has no answer, your system goes here to find out which DNS server to ask. It looks like:</p>
<pre><code class="language-plaintext">nameserver 8.8.8.8
nameserver 8.8.4.4
</code></pre>
<p>The above example shows Google's DNS severs. You can also use <code>1.1.1.1</code> which is Cloudflare's.</p>
<h3><code>/etc/nsswitch.conf</code></h3>
<p>This is the traffic controller of the whole resolution process. It defines the order in which your system looks things up. The relevant line looks like:</p>
<pre><code class="language-plaintext">hosts: files dns
</code></pre>
<p>This tells the system: first check files (which means <code>/etc/hosts</code>), then go to dns (which means <code>/etc/resolv.conf</code>). This is why <code>/etc/hosts</code> always wins over DNS servers.</p>
<h3>The full DNS resolution flow</h3>
<ol>
<li><p>Check <code>/etc/nsswitch.conf</code> for the lookup order</p>
</li>
<li><p>Check <code>/etc/hosts</code> for a static entry</p>
</li>
<li><p>No match? Go to <code>/etc/resolv.conf</code> for the DNS server</p>
</li>
<li><p>Ask that DNS server for <code>google.com</code></p>
</li>
<li><p>Get the IP back, connect</p>
</li>
</ol>
<hr />
<h2>Network Interface Configuration</h2>
<p>A network interface is your system's way of connecting to a network. It can be physical, like your ethernet port or WiFi card, or virtual, like a loopback interface. Each interface gets a name:</p>
<ul>
<li><p><code>eth0</code> or <code>enp3s0</code>: your ethernet card</p>
</li>
<li><p><code>wlan0</code> or <code>wlp2s0</code>: your WiFi card</p>
</li>
<li><p><code>lo</code>: the loopback interface, always <code>127.0.0.1</code>, used by your system to talk to itself</p>
</li>
</ul>
<p>You can see all your interfaces with:</p>
<pre><code class="language-bash">ip link show
</code></pre>
<p>The location of these network config files varies by distro, which is one of the few places where the FHS does not give you full uniformity.</p>
<p>For Debian and older Ubuntu systems, the file is located at <code>/etc/network/interfaces</code>:</p>
<pre><code class="language-plaintext">auto eth0
iface eth0 inet dhcp
</code></pre>
<p>This says: bring up <code>eth0</code> automatically on boot, and get its IP via DHCP.</p>
<hr />
<h2>Service Configurations</h2>
<p>When you run <code>systemctl start nginx</code> or <code>systemctl enable ssh</code>, systemd needs to know:</p>
<ul>
<li><p>What those services actually are?</p>
</li>
<li><p>How should they start?</p>
</li>
<li><p>What user should run them?</p>
</li>
<li><p>What happens if they crash?</p>
</li>
</ul>
<p>All of this is defined in a unit file.</p>
<p><code>/etc/systemd/system/</code> is where your local unit files live. These are either custom services you created yourself, or overrides to the default unit files that came with installed packages.</p>
<h3>What does a unit file look like?</h3>
<p>Let's look at a simple example. Say you want to create a service that runs a Node.js app on boot:</p>
<pre><code class="language-plaintext">[Unit]
Description=My Node.js App
After=network.target

[Service]
ExecStart=/usr/bin/node /home/sameer/app/index.js
Restart=always
User=sameer
</code></pre>
<p>Breaking down the two sections:</p>
<ul>
<li><p><code>[Unit]</code>: Metadata about the service.</p>
<ul>
<li><code>After=network.target</code>: Don't start this service until the network is up.</li>
</ul>
</li>
<li><p><code>[Service]</code>: The actual behavior</p>
<ul>
<li><p><code>ExecStart</code>: the command to run</p>
</li>
<li><p><code>Restart=always</code>: if the process crashes, restart it automatically</p>
</li>
<li><p><code>User</code>: run the process as this user, not as root</p>
</li>
</ul>
</li>
</ul>
<h3>Enabling vs Starting</h3>
<p>There is an important distinction here that trips up a lot of beginners:</p>
<pre><code class="language-plaintext">systemctl start nginx    # starts the service right now
systemctl enable nginx   # makes it start automatically on every boot
</code></pre>
<p><code>start</code> is temporary. <code>enable</code> is permanent. You almost always want both:</p>
<pre><code class="language-plaintext">systemctl enable --now nginx
</code></pre>
<p>The <code>--now</code> flag starts it immediately and enables it for future boots in one command.</p>
<h3>Where do default unit files live then?</h3>
<p>If <code>/etc/systemd/system/</code> is for local configs, where do the unit files for packages like <code>nginx</code> or <code>ssh</code> live? Those ship to <code>/usr/lib/systemd/system/</code>.</p>
<p>The rule is simple: <code>/etc/systemd/system/</code> always takes priority over <code>/usr/lib/systemd/system/</code>. So if you want to override how a package's service behaves without touching the original file, you drop your version in <code>/etc/systemd/system/</code> and systemd will use that instead.</p>
<hr />
<h2><code>/proc</code>: The Process Filesystem</h2>
<p><code>/proc</code> is one of those things that genuinely makes you stop and think. It looks like a directory full of files, but none of these files actually exist on your disk. There is nothing written to your SSD or HDD here.</p>
<p><code>/proc</code> is a virtual filesystem that the kernel generates in memory, live, every time you look at it.</p>
<p>Think of it as a window into your running kernel. Whatever is happening on your system right now, the kernel is exposing it as readable files inside <code>/proc</code>. The moment a process starts, an entry appears. The moment it dies, it disappears.</p>
<p>You can verify this yourself:</p>
<pre><code class="language-plaintext">ls /proc
</code></pre>
<p>You will see a bunch of numbered directories like <code>1</code>, <code>423</code>, <code>1089</code> and so on. Each number is a PID (Process ID), and each directory contains information about that running process. Open one up:</p>
<pre><code class="language-plaintext">ls /proc/1
</code></pre>
<p>You will find files like <code>status</code>, <code>cmdline</code>, <code>maps</code>, <code>fd</code> and more, all describing exactly what that process is doing right now.</p>
<p>For example:</p>
<pre><code class="language-plaintext">cat /proc/1/status
</code></pre>
<p>This will show you the name of the process, its state, memory usage, which user is running it, and more. All of that, served as a plain text file.</p>
<p>This is the "everything is a file" philosophy at its most elegant. The kernel is not a black box. It is constantly talking to you through <code>/proc</code>, and all you need to read it is <code>cat</code>.</p>
<hr />
<h2>Routing Tables</h2>
<p>When your system wants to send a packet to some IP address, it does not just blindly throw it onto the network. It first consults a routing table, which is essentially a set of rules that answer one question: for this destination, which interface should I use and where should I forward the packet?</p>
<p>A simple way to see your routing table is:</p>
<pre><code class="language-plaintext">ip route show
</code></pre>
<p>You will see something like:</p>
<pre><code class="language-plaintext">default via 192.168.1.1 dev wlan0
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.105
</code></pre>
<ul>
<li><p>The first line says: for everything else, forward to <code>192.168.1.1</code> (your router) via <code>wlan0</code>.</p>
</li>
<li><p>The second line says: for anything in the <code>192.168.1.0/24</code> range, you can reach it directly through <code>wlan0</code> without going through a gateway.</p>
</li>
</ul>
<p>Now, this same information is also exposed as a file inside <code>/proc</code>:</p>
<pre><code class="language-plaintext">cat /proc/net/route
</code></pre>
<pre><code class="language-plaintext">Iface    Destination  Gateway   Flags  RefCnt  Use  Metric  Mask
wlan0    00000000     0101A8C0  0003   0       0    100     00000000
wlan0    0001A8C0     00000000  0001   0       0    100     00FFFFFF
</code></pre>
<p>This is the raw version of the same routing table, but in hex. The values for Destination, Gateway and Mask are in little endian hex format, which is why <code>0101A8C0</code> translates to <code>192.168.1.1</code>. Not the most human readable format, which is exactly why tools like <code>ip route</code> exist on top of it.</p>
<p>The key insight here is that <code>/proc/net/route</code> is not a config file. You cannot edit it to change your routes. It is purely a read only window into what the kernel currently knows about routing, consistent with the whole philosophy of <code>/proc</code>.</p>
<hr />
<h2>System Logs</h2>
<p>When something goes wrong on your system, the first place you go is <code>/var/log</code>. This is where Linux keeps logs for pretty much everything: the kernel, system services, applications, authentication events, and more.</p>
<pre><code class="language-plaintext">ls /var/log
</code></pre>
<p>You will see a bunch of files and directories. Here are the important ones:</p>
<pre><code class="language-plaintext">/var/log
├── syslog     -&gt; General system activity logs (Debian/Ubuntu)
├── auth.log   -&gt; Authentication events (logins, sudo usage)
├── kern.log   -&gt; Kernel messages
├── dmesg      -&gt; Boot time hardware detection logs
└── journal/   -&gt; systemd's binary log store
</code></pre>
<h3>Reading logs</h3>
<p>For most log files, a simple <code>cat</code> or <code>tail</code> works:</p>
<pre><code class="language-plaintext">tail -f /var/log/auth.log
</code></pre>
<p>The <code>-f</code> flag follows the file in real time, so you can watch events as they come in. Useful for monitoring login attempts or debugging a service.</p>
<p>For systemd based systems, the preferred way to read logs is through <code>journalctl</code>:</p>
<pre><code class="language-plaintext">journalctl -u nginx        # logs for a specific service
journalctl -f              # follow logs in real time
journalctl --since today   # logs from today only
</code></pre>
<h3>What insights do logs actually give you?</h3>
<p>A few practical examples of what you can catch from logs:</p>
<ul>
<li><p>Someone repeatedly trying to SSH into your server with wrong passwords: visible in <code>auth.log</code></p>
</li>
<li><p>A service that keeps crashing on boot: visible in <code>journalctl -u servicename</code></p>
</li>
<li><p>A kernel panic or hardware error: visible in <code>kern.log</code> or <code>dmesg</code></p>
</li>
<li><p>General system misbehavior: visible in <code>syslog</code></p>
</li>
</ul>
<hr />
<h2>File Descriptors</h2>
<p>When a program opens a file, the kernel does not give it direct access to the file. Instead, it gives back a small integer called a file descriptor. This integer is just a reference that the program uses to interact with the file going forward.</p>
<p>Every process gets three file descriptors by default when it starts:</p>
<pre><code class="language-plaintext">0 -&gt; stdin  (standard input)
1 -&gt; stdout (standard output)
2 -&gt; stderr (standard error)
</code></pre>
<p>When the program opens additional files, they get assigned the next available numbers: <code>3</code>, <code>4</code>, <code>5</code> and so on.</p>
<p>You can see the file descriptors of any running process through <code>/proc</code>:</p>
<pre><code class="language-plaintext">ls /proc/&lt;PID&gt;/fd
</code></pre>
<p>This will show you every file, socket, pipe or device that process currently has open, each represented as a numbered symlink.</p>
<h3>Everything is a File Descriptor</h3>
<p>This is where the "everything is a file" philosophy gets very practical. In Linux, file descriptors are not just for files on disk. They represent:</p>
<ul>
<li><p>Regular files</p>
</li>
<li><p>Directories</p>
</li>
<li><p>Network sockets</p>
</li>
<li><p>Pipes between processes</p>
</li>
<li><p>Device files in <code>/dev</code></p>
</li>
</ul>
<p>When your Node.js server accepts an incoming HTTP connection, the kernel hands it a file descriptor for that socket. The server reads from it and writes to it just like a regular file. Same interface, whether it is a text file or a network connection.</p>
<h3>The Default Limit and Why it Matters</h3>
<p>The kernel puts a limit on how many file descriptors a single process can have open at once. You can check yours with:</p>
<pre><code class="language-plaintext">ulimit -n
</code></pre>
<p>On most systems this defaults to <code>1024</code>. This means a single process can have at most 1024 files, sockets, or connections open at the same time.</p>
<p>For a simple script or a CLI tool, 1024 is more than enough. But for a web server or a WebSocket server, this becomes a real problem fast.</p>
<h3>The WebSocket Problem</h3>
<p>A WebSocket server maintains a persistent open connection with every connected client. Each connection is a file descriptor. So if you have 1024 concurrent users connected to your WebSocket server, you have hit the limit. The 1025th user cannot connect. The kernel will throw a <code>Too many open files</code> error and your server will start rejecting connections.</p>
<p>This is not a bug in your code. It is a system level limit you need to raise.</p>
<h3>Raising the Limit</h3>
<p>There are two limits to be aware of:</p>
<pre><code class="language-plaintext">ulimit -n   # soft limit, applies to your current session
</code></pre>
<p>To raise it permanently, you edit <code>/etc/security/limits.conf</code>:</p>
<pre><code class="language-plaintext">*    soft    nofile    65536
*    hard    nofile    65536
</code></pre>
<p>The <code>*</code> applies to all users. <code>nofile</code> stands for number of open files. <code>65536</code> is a common production value for web servers.</p>
<p>For systemd managed services, you set it directly in the unit file instead:</p>
<pre><code class="language-plaintext">[Service]
LimitNOFILE=65536
</code></pre>
<p>After making these changes, restart the service and verify:</p>
<pre><code class="language-plaintext">cat /proc/&lt;PID&gt;/limits
</code></pre>
<p>This is one of the first things you tune when deploying a WebSocket server or any high concurrency application in production. A server with default limits will quietly start failing under load, and the logs will tell you exactly why.</p>
<hr />
<h2>Conclusion</h2>
<p>In the end, the Linux filesystem is far more than a collection of folders. It reflects a philosophy of simplicity, consistency, and treating system resources through one unified interface.</p>
<p>Once you understand what lives where, Linux stops feeling mysterious and starts feeling logical. And as developers, that understanding gives us a real edge when working with servers, debugging production systems, or simply feeling more at home inside the machines that run the modern web.</p>
]]></content:encoded></item><item><title><![CDATA[Cache Strategies in Distributed Systems]]></title><description><![CDATA[Introduction
In large-scale distributed systems, performance is not an option, but a necessity. Imagine if platforms like YouTube or Twitter slowed down or went completely offline for a few hours. In ]]></description><link>https://blog.sameerbhagtani.dev/cache-strategies-in-distributed-systems</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/cache-strategies-in-distributed-systems</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[System Design]]></category><category><![CDATA[distributed systems]]></category><category><![CDATA[caching]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Wed, 18 Mar 2026 15:32:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/b4c83276-a342-4f2e-a7b7-51825a9f4382.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>In large-scale distributed systems, performance is not an option, but a necessity. Imagine if platforms like YouTube or Twitter slowed down or went completely offline for a few hours. In today’s world, we rely heavily on such systems, and they are expected to respond with low latency at all times.</p>
<p>A common approach to reducing latency is caching. A cache is simply a high-speed, temporary, and often in-memory data storage layer that stores a subset of frequently accessed data. It allows us to serve future requests faster, without having to hit the primary storage, such as the database.</p>
<p>This not only reduces latency but also decreases the load on the database, enabling the system to handle massive traffic efficiently.</p>
<p>Typically, every cached item has a TTL (Time-To-Live) associated with it. Once the TTL expires (for example, after 60 seconds), the cache is invalidated, and fresh data is fetched from the database as needed. This approach works well for small systems, but this naive model begins to break down at scale.</p>
<p>In distributed systems, cache expiration can lead to sudden traffic spikes, resulting in issues like the thundering herd problem. (You can read more about this in my blog post on the <a href="https://blog.sameerbhagtani.dev/thundering-herd-problem">thundering herd problem</a>.)</p>
<hr />
<h2>Basic TTL Caching is Not Enough</h2>
<p>A basic TTL-based caching approach looks like this:</p>
<blockquote>
<p>Data is cached -&gt; requests are served from the cache -&gt; TTL expires -&gt; a new request comes in, triggering a fetch from the database -&gt; and the cycle continues.</p>
</blockquote>
<p>This works well when traffic is evenly distributed and requests arrive at random intervals. In smaller systems, this approach is often sufficient.</p>
<p>However, in large-scale systems, traffic is rarely uniform. It is often bursty, with many users requesting the same data at the same time. When the cache for such frequently accessed data expires, a large number of requests suddenly start missing the cache and go directly to the database, all at once.</p>
<p>This leads to sudden load spikes, increased latency, and potential system failures.</p>
<hr />
<h2>Cache Expiry can Cause Traffic Spikes</h2>
<p>Consider the example of a social media platform, which caches popular posts to increase the overall speed. Assume the cache TTL is 60 seconds.</p>
<p>If everything is going fine, requests will hit our server, the server will fetch the post content from the cache, and return it in the response. There is no database call, and thus shorter request-response cycles.</p>
<p>However, after the 60 seconds have gone by and the cache expires, if a large number of requests come in simultaneously, since the cache is empty, each and every request will go straight to the database at the same time, resulting in the thundering herd problem. This can overload the database, increase latency, and even lead to request failures.</p>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/5ee940b7-f7c5-4b2f-aef7-d433d5e311c2.png" alt="" style="display:block;margin:0 auto" />

<p>Clearly, we need smarter strategies to handle cache expiration in distributed systems.</p>
<hr />
<h2>Cache Management Strategies for Distributed Systems</h2>
<h3>TTL Jitter</h3>
<p>Up until now, we’ve understood that the core issue is many cached items expiring at the same time. This causes a large number of requests to hit the database simultaneously, leading to chaos. The problem isn’t traffic itself, large-scale systems are expected to handle high traffic. The real issue is <strong>synchronized traffic</strong>.</p>
<p>TTL Jitter is a simple yet effective strategy that introduces randomness into cache expiration times. Instead of assigning a fixed TTL (for example, 60 seconds), we add a small variation and set the TTL within a range, such as 50–70 seconds.</p>
<pre><code class="language-plaintext">ttl = baseTTL + random(-delta, +delta)
</code></pre>
<p>As a result, cache entries expire at different times, and incoming requests get naturally distributed instead of creating sudden spikes.</p>
<ul>
<li><p><strong>Without jitter:</strong> 10k keys expire at exactly 60s -&gt; spike</p>
</li>
<li><p><strong>With jitter:</strong> keys expire at 58s, 61s, 64s -&gt; smoother load distribution</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/cdd97c94-17b4-482c-8932-1d87ca943dc9.png" alt="" style="display:block;margin:0 auto" />

<h3>Probability-Based Early Expiration</h3>
<p>The limitation of TTL jitter is that cache entries still expire eventually. Requests will still hit the database, we’ve only found a way to distribute them more evenly.</p>
<p>To handle this more effectively, we can take a proactive approach using probabilistic early expiration.</p>
<p>Instead of waiting for the TTL to reach zero, we allow some requests to refresh the cache before it actually expires. However, we don’t want every request to do this, as that would create unnecessary load. So, we introduce probability into the decision.</p>
<p>Each incoming request has a certain chance of recomputing the cached value early. This probability is not fixed, it increases as the cache gets closer to expiration.</p>
<ul>
<li><p>When the TTL has just been set -&gt; very low probability of recomputation</p>
</li>
<li><p>As the TTL decreases -&gt; probability gradually increases</p>
</li>
<li><p>Near expiration -&gt; high probability of recomputation</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/3b617c14-2ab3-441a-bb74-420f615def05.png" alt="" style="display:block;margin:0 auto" />

<p>Thus, instead of reacting at the deadline like basic TTL-based caching, this method prepares the system gradually.</p>
<h3>Mutex / Cache Locking</h3>
<p>Even with strategies like TTL jitter and probabilistic early expiration, there are still situations where multiple requests may try to recompute the same cache entry at the same time. This leads to duplicate work, where several requests hit the database simultaneously for the same data, increasing load and reducing efficiency.</p>
<p>To solve this, we can use <strong>mutex (mutual exclusion)</strong> or <strong>cache locking</strong>. When a cache entry expires and multiple requests try to fetch fresh data, only one request is allowed to recompute the value, while the others wait.</p>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/282d1b91-fb0e-4e42-8614-67a5cbbe30ff.png" alt="" style="display:block;margin:0 auto" />

<p>The simple flow is:</p>
<ul>
<li><p>A request checks the cache</p>
</li>
<li><p>If the cache is missing or expired -&gt; it tries to acquire a lock</p>
</li>
<li><p>If it gets the lock -&gt; it fetches data from the database and updates the cache</p>
</li>
<li><p>If it doesn’t get the lock -&gt; it waits until the cache is updated</p>
</li>
</ul>
<p>The tradeoff is that this introduces additional latency for waiting requests.</p>
<h3>Stale-While-Revalidate (SWR)</h3>
<p>Even with techniques like mutex locking, some requests may still have to wait while the cache is being recomputed. This introduces additional latency, which can negatively impact user experience.</p>
<p>The idea behind SWR is: instead of blocking requests when the cache expires, we serve the stale (expired) data and refresh the cache in the background.</p>
<p>In this approach, a cached item can exist in two states:</p>
<ol>
<li><p>Fresh -&gt; within TTL, safe to serve</p>
</li>
<li><p>Stale -&gt; TTL expired, but still usable for a short duration</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/88ca7481-0236-44b5-9f5e-57518b558601.png" alt="" style="display:block;margin:0 auto" />

<p>Because of this, users never have to wait for recomputation. The system continues to serve responses with low latency, while the cache gets updated asynchronously.</p>
<p>However, the tradeoff is that users may receive stale data for a short period of time. Because of this, SWR is not suitable for systems that require strict consistency, such as financial transactions or real-time critical data.</p>
<h3>Cache Warming</h3>
<p>So far, all the strategies we’ve discussed deal with cache behavior during runtime. But what if we could prepare the cache before requests even start coming in?</p>
<p>This is where cache warming (or pre-warming) comes in.</p>
<p>The idea is simple: instead of waiting for users to request data and then populating the cache (lazy loading), we proactively load frequently accessed data into the cache in advance.</p>
<p>This ensures that when the first request arrives, the data is already available in the cache, avoiding initial cache misses.</p>
<p>This can be done using:</p>
<ul>
<li><p>background jobs</p>
</li>
<li><p>scheduled tasks (cron jobs)</p>
</li>
<li><p>analytics-based predictions</p>
</li>
</ul>
<hr />
<h2>Conclusion</h2>
<p>Caching is not just about storing data to make systems faster, it’s about making the system stable under load.</p>
<p>Each of these techniques makes a tradeoff between freshness, latency, and consistency. There is no one-size-fits-all solution, the right approach depends on the nature of your system and the type of data you are dealing with.</p>
]]></content:encoded></item><item><title><![CDATA[The Thundering Herd Problem in System Design]]></title><description><![CDATA[Introduction
Imagine you're standing outside an Apple Store, waiting for the new iPhone to launch. Obviously, you're not alone. You're just one among a big crowd waiting for that door to open. As soon]]></description><link>https://blog.sameerbhagtani.dev/thundering-herd-problem</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/thundering-herd-problem</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[System Design]]></category><category><![CDATA[thundering-herd]]></category><category><![CDATA[distributed systems]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Tue, 17 Mar 2026 21:50:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/aa53afbb-afe6-472a-af64-bfdaad4cb21c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Imagine you're standing outside an Apple Store, waiting for the new iPhone to launch. Obviously, you're not alone. You're just one among a big crowd waiting for that door to open. As soon as it does, each and every single person in the crowd rushes in, out of the fear of getting left behind. And before you know it, you're caught up in chaos, everyone pushing each other around, overloading the store.</p>
<p>This is exactly what is called the "Thundering Herd Problem" in the context of system design. Many clients make a request at the same time and overwhelm a resource (server, database, etc.).</p>
<hr />
<h2>What is the Thundering Herd Problem?</h2>
<p>We all try to make our systems robust and fast, for which we adopt different system design patterns like scaling, caching, etc. However, certain loopholes in our system can lead to the "Thundering Herd Problem." Even large, robust systems suffer from this problem.</p>
<p>The Thundering Herd Problem simply refers to a large number of clients requesting a resource simultaneously, often reacting to the same event at the same time. It is not just high volume; it is simultaneous high volume.</p>
<p>Despite how the name sounds, it is important to understand that the Thundering Herd Problem is not a bug. It's just a pattern that occurs in systems with a large client base, and we need to understand why it occurs and how we can fix it.</p>
<hr />
<h2>Where Does it Commonly Occur?</h2>
<p>This problem can occur in multiple parts of a system, such as caching systems, load balancers, etc., due to different reasons:</p>
<ul>
<li><p><strong>Cache Stampede:</strong> When a highly accessed cached item expires, multiple concurrent requests bombard the database to refill the cache.</p>
</li>
<li><p><strong>Synchronized Retries:</strong> If a service fails to respond for a short period of time and then comes back online, many clients simultaneously retry failed requests, creating a spike in traffic.</p>
</li>
<li><p><strong>Cron Jobs:</strong> Multiple servers or microservices are configured to run a cron job at the exact same scheduled time.</p>
</li>
<li><p><strong>Sudden Traffic Spikes:</strong> A sudden influx of users all attempting to perform the same action at the same time, such as clicking a "Buy Now" button during a flash sale.</p>
</li>
</ul>
<hr />
<h2>Real World Example</h2>
<p>Consider the example of a social media platform, which caches popular posts to increase the overall speed. Assume the cache TTL is 60 seconds.</p>
<p>If everything is going fine, requests will hit our server, the server will fetch the post content from the cache, and return it in the response. There is no database call, and thus shorter request-response cycles.</p>
<p>However, after the 60 seconds have gone by and the cache expires, if a large number of requests come in simultaneously, since the cache is empty, each and every request will go straight to the database at the same time, resulting in the thundering herd problem.</p>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/f912896d-40e6-4dc3-a79f-3483f51238a6.png" alt="" style="display:block;margin:0 auto" />

<p>This can overload the database, increase latency, and even lead to request failures.</p>
<hr />
<h2>Difference Between Normal Spike vs Thundering Herd</h2>
<p>In normal situations, traffic spikes happen gradually. Imagine Hotstar starts streaming IPL live. Viewers keep joining over time, and our auto-scaling configuration is able to scale the servers to handle the increasing load.</p>
<p>On the other hand, in a thundering herd situation, all the traffic comes in at once. It is not gradual, it is instantaneous and unpredictable. This results in more load on the servers and databases than the system can handle.</p>
<p>In such situations, we often enter into a chain reaction:</p>
<blockquote>
<p>More requests -&gt; DB connections get exhausted -&gt; requests start waiting -&gt; latency increases → timeouts happen → clients retry → even more load. 💥</p>
</blockquote>
<hr />
<h2>Why it Becomes Dangerous in Distributed Systems</h2>
<p>Now that you have understood the thundering herd problem, it is important to understand its impact in the context of distributed systems.</p>
<p>Distributed systems amplify this problem even further:</p>
<ul>
<li><p>There are many services and instances involved. If every request triggers 5 services, then with a spike of 100k requests, we are effectively dealing with 500k internal requests.</p>
</li>
<li><p>If one service slows down, other services depending on it also slow down, leading to cascading failures across the system.</p>
</li>
<li><p>Each service might implement its own retry logic, resulting in multiple retries across multiple services, which further multiplies the load.</p>
</li>
<li><p>Many services rely on shared resources like databases, caches, or message queues. When all services hit these resources simultaneously, they become bottlenecks and can fail under pressure.</p>
</li>
</ul>
<p>Failures in distributed systems propagate and amplify, making the thundering herd problem significantly more dangerous.</p>
<hr />
<h2>System-Level Impact</h2>
<ul>
<li><p><strong>CPU:</strong> A sudden surge in requests increases the number of active threads and processes, causing CPU usage to spike. This can lead to excessive context switching and reduced overall efficiency.</p>
</li>
<li><p><strong>Database:</strong> A large number of concurrent queries can exhaust the connection pool, slow down query execution, and potentially crash the database under heavy load.</p>
</li>
<li><p><strong>Cache:</strong> During a cache miss storm, the cache becomes temporarily ineffective, forcing repeated requests to hit the database and increasing pressure on backend systems.</p>
</li>
<li><p><strong>Latency:</strong> As requests start queuing up, response times increase significantly. This leads to timeouts, failed requests, and a poor user experience.</p>
</li>
</ul>
<p>The impact is not isolated, it affects every layer of the system.</p>
<hr />
<h2>Techniques to Minimize It</h2>
<h3>Request Coalescing</h3>
<p>Instead of allowing all requests to go to the database to refill the cache, we ensure that only one request performs this operation. When multiple requests arrive for the same data, one request fetches the data from the database and updates the cache, while the others wait and reuse the same result.</p>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/78aa4583-f2fb-4dd5-bffb-39c9d09f86f1.png" alt="" style="display:block;margin:0 auto" />

<p>This prevents duplicate work and reduces unnecessary load on the database.</p>
<h3>Cache Locking / Mutex</h3>
<p>Cache locking (or mutex) is a technique used to ensure that only one request can regenerate the cache at a time. When a request detects a cache miss, it acquires a lock and proceeds to fetch data from the database. Other requests are blocked or wait until the lock is released.</p>
<h3>Staggered Expiry</h3>
<p>Staggered Expiry is another technique that focuses on making sure that all the cached data does not expire at once. To achieve this, we introduce a small random variation (jitter) in their expiry times.</p>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/d8657fe7-e4f0-456a-aaf1-cfa3497fc225.png" alt="" style="display:block;margin:0 auto" />

<p>This reduces the chances of a sudden spike in load, by spreading out requests over time.</p>
<h3>Exponential Backoff</h3>
<p>When a request fails, you don’t just try again right away. With exponential backoff, you wait a bit, and each time you fail again, you wait even longer. The delay grows fast, so clients don’t all hammer the server at once.</p>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/2e02f9df-c263-4370-b148-487c0a33fc56.png" alt="" style="display:block;margin:0 auto" />

<p>It spreads out the load and keeps the system from getting overloaded.</p>
<h3>Rate Limiting</h3>
<p>Rate limiting sets a cap on how many times a client can hit the system in a given period. If you go over that number, your requests get blocked or slowed down. This keeps the service from getting swamped and makes sure everyone gets a fair shot at the resources.</p>
<hr />
<h2>Conclusion</h2>
<p>The thundering herd problem is not caused by high traffic alone, but by many requests happening at the same time due to a shared trigger. While it can lead to serious issues in distributed systems, it can be effectively managed using the right techniques such as request coalescing, staggered expiry, backoff strategies, and rate limiting.</p>
<p>By understanding the root cause and applying these strategies, we can build systems that remain stable even under sudden spikes in load.</p>
]]></content:encoded></item><item><title><![CDATA[Operators: Welcome to the JavaScript Cafe]]></title><description><![CDATA[Introduction
Imagine walking into a cafe called the "JavaScript Cafe". Just like any other typical cafe, this one too has several ingredients, chefs who decide what to do with these ingredients as per]]></description><link>https://blog.sameerbhagtani.dev/operators-in-javascript</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/operators-in-javascript</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Operators]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Sat, 07 Mar 2026 22:34:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/1b9b87d1-bc66-4d81-8225-69148f4e9aeb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Imagine walking into a cafe called the "JavaScript Cafe". Just like any other typical cafe, this one too has several ingredients, chefs who decide what to do with these ingredients as per the customer's wishes, and finally they create some dish based on the requirements.</p>
<p>If you think about it, we basically take some data (ingredients), put them together using some operations (as decided by the chefs), and create a final dish (result).</p>
<p>Programming works in a similar fashion. In every programming language, including JavaScript, we have a foundational concept called operators. In this blog post, we are going to explore what operators are, how they help us build expressions and all the different types of operators, all with a fun analogy of a cafe, particularly the JavaScript Cafe!</p>
<hr />
<h2>Tokens: Building Blocks of any Language</h2>
<p>Before we get into operators, let's briefly talk about tokens. Whenever we write any program, the compiler/interpreter behind that language breaks it all down into tokens. Tokens are the smallest meaningful units of code in any language. The JavaScript engine also breaks down the code into these bits and pieces called tokens.</p>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/d3cdfec4-1c5d-4a50-b7d8-129c37f2b1c1.png" alt="Diagram showing how the JavaScript statement let x = 5; is broken into tokens: let (keyword), x (identifier), = (operator), 5 (literal), and ; (separator)." style="display:block;margin:0 auto" />

<p>You can think of tokens like words in a sentence. Just like sentences are made of words, programs are made up of tokens.</p>
<p>JavaScript has the following types of tokens:</p>
<h3>Keywords</h3>
<p>These are reserved or pre-defined words that have a special meaning.</p>
<p>Examples include:</p>
<pre><code class="language-javascript">let
const
function
return
if
else
class
await
</code></pre>
<h3>Identifiers</h3>
<p>These are names that we programmers give to variables, functions, classes, or objects.</p>
<p>Examples include:</p>
<pre><code class="language-javascript">let username = "Sameer";

function add(a, b) {
    return a + b;
}
</code></pre>
<ul>
<li>In the above example, <code>username</code> and <code>add</code> are identifiers.</li>
</ul>
<h3>Literals</h3>
<p>These represent fixed values written directly in code.</p>
<p>Examples include:</p>
<pre><code class="language-javascript">42
"Hello"
true
null
</code></pre>
<h3>Separators</h3>
<p>These are symbols used to structure the code.</p>
<p>Examples include:</p>
<pre><code class="language-javascript">;
,
.
()
{}
[]
:
</code></pre>
<h3>Comments</h3>
<p>Comments are simply some annotations in our code, that are straight up ignored by the JavaScript engine. These are useful for documentation.</p>
<p>Examples include:</p>
<pre><code class="language-javascript">// this is a single line comment

/*
this is a
multi-line
comment
*/
</code></pre>
<h3>Operators</h3>
<p>And finally, we have our operators. This blog post is specifically about operators in JavaScript. However, this brief section was important to help you understand that operators are simply some of many tokens that have a special meaning to the language.</p>
<p>Now what exactly are operators, why do we need them, etc. will all be covered in the rest of this blog post.</p>
<hr />
<h2>What are Operators?</h2>
<p>Before getting into the types of operators, we need to understand what they even are, and why do we need them. The definition goes like:</p>
<blockquote>
<p>Operators are symbols or keywords in programming that perform operations on variables and values (operands) to manipulate data.</p>
</blockquote>
<p>However, such long and boring technical definitions do not enable us to understand and remember the concept easily. So let's take the example of our JavaScript Cafe. Let's say you walk into this beautiful Cafe, and order for a coffee. Based on your requirements, the chefs will gather all the ingredients and prepare a coffee for you.</p>
<p>Now this simple process involved the following parts:</p>
<ul>
<li><p>Ingredients</p>
</li>
<li><p>Actions performed by the chefs on the ingredients</p>
</li>
<li><p>Your coffee</p>
</li>
</ul>
<p>Similarly, in the context of programming, we have some input data (ingredients), and we want to get the output i.e. the final result (the coffee). In order to do that, it is required to perform certain actions on that input data (actions performed by the chefs).</p>
<p>Operators are the symbols that help us perform these actions. They are simply that glue, that help us put together some data, and generate some result. The simplest example would be:</p>
<pre><code class="language-javascript">5 + 2
</code></pre>
<p>Here, <code>+</code> is an operator, whose job is to sum up the numbers given to it.</p>
<hr />
<h2>Expressions</h2>
<p>Now that we have a basic idea about operators, we need to understand one more term, which is pretty common in programming languages. An expression is simply a valid unit of code that evaluates to a single value. This value can be a number, a string, a boolean value, a function, etc.</p>
<p>In our analogy, we can think of an expression like an "order". In order to complete an order, we use several ingredients, instructions given by the customer, etc., and in the end we put it all together, to create a final dish.</p>
<p>Example:</p>
<pre><code class="language-javascript">5 + 2
</code></pre>
<p>This is a very simple expression. It produces the value <code>7</code>.</p>
<p>Here,</p>
<ul>
<li><p><code>5</code> &amp; <code>2</code> are the operands</p>
</li>
<li><p><code>+</code> is the operator (just like we saw in the last section)</p>
</li>
<li><p><code>7</code> is the output produced</p>
</li>
</ul>
<h3>Structure of expressions</h3>
<p>Such expressions are built using operators. And we can use any valid combination of operators, to create any type of expression, no matter how simple or complex. A simple structure is given below:</p>
<img src="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/6530bc99-02d5-43c1-a830-55dfbbdd7ce8.png" alt="Diagram illustrating operators and operands using the expression 5 + 2 * 6, where + and * are operators and 5, 2, and 6 are operands." style="display:block;margin:0 auto" />

<hr />
<h2>Types of Operators in JavaScript</h2>
<p>Now that we understand what operators and expressions are, let's deep dive into the types of operators in JavaScript. Some of these concepts, even extend to other programming languages, since operators is a fundamental concept.</p>
<p>Following are the most commonly used types of operators in JavaScript:</p>
<ol>
<li><p>Arithmetic Operators</p>
</li>
<li><p>Comparison/Relational Operators</p>
</li>
<li><p>Logical Operators</p>
</li>
<li><p>Assignment Operators</p>
</li>
<li><p>Conditional/Ternary Operator</p>
</li>
</ol>
<hr />
<h2>Arithmetic Operators</h2>
<p>Arithmetic operators allow us to perform certain mathematical operations on data. Whenever we want to add, subtract, divide, multiply, etc. any values or variables, we make use of such arithmetic operators.</p>
<p>Think of them as how chefs add, remove, combine, etc. several ingredients to make dishes.</p>
<table>
<thead>
<tr>
<th>Operator</th>
<th>Meaning</th>
<th>Analogy</th>
</tr>
</thead>
<tbody><tr>
<td><code>+</code></td>
<td>Addition</td>
<td>Mix ingredients</td>
</tr>
<tr>
<td><code>-</code></td>
<td>Subtraction</td>
<td>Remove ingredients</td>
</tr>
<tr>
<td><code>*</code></td>
<td>Multiplication</td>
<td>Add an ingredient multiple times</td>
</tr>
<tr>
<td><code>/</code></td>
<td>Division</td>
<td>Split portions</td>
</tr>
<tr>
<td><code>%</code></td>
<td>Modulus</td>
<td>Find leftovers</td>
</tr>
<tr>
<td><code>**</code></td>
<td>Exponentiation</td>
<td>Multiply an ingredient multiple times</td>
</tr>
<tr>
<td><code>++</code></td>
<td>Increment</td>
<td>Add one extra ingredient</td>
</tr>
<tr>
<td><code>--</code></td>
<td>Decrement</td>
<td>Remove one ingredient</td>
</tr>
</tbody></table>
<h3>Example Code</h3>
<pre><code class="language-javascript">console.log(12 + 8);    // 20
console.log(15 - 6);    // 9
console.log(4 * 5);     // 20
console.log(20 / 4);    // 5
console.log(14 % 4);    // 2
console.log(3 ** 4);    // 81

let count = 10;
count++;
console.log(count);     // 11

count--;
console.log(count);     // 10
</code></pre>
<hr />
<h2>Comparison/Relational Operators</h2>
<p>If arithmetic operators are like preparing ingredients, then comparison operators are like checking ingredients before cooking.</p>
<p>Comparison operators, often referred to as Relational operators, allow us to compare data in our program. These always return a boolean value (<code>true</code> or <code>false</code>). These are very useful when writing conditional statements.</p>
<table>
<thead>
<tr>
<th>Operator</th>
<th>Meaning</th>
<th>Analogy</th>
</tr>
</thead>
<tbody><tr>
<td><code>==</code></td>
<td>Equal to</td>
<td>Check if two ingredients look the same</td>
</tr>
<tr>
<td><code>===</code></td>
<td>Strict equal to</td>
<td>Check if two ingredients are exactly the same</td>
</tr>
<tr>
<td><code>!=</code></td>
<td>Not equal to</td>
<td>Check if two ingredients are different</td>
</tr>
<tr>
<td><code>!==</code></td>
<td>Strict not equal to</td>
<td>Check if two ingredients are completely different</td>
</tr>
<tr>
<td><code>&gt;</code></td>
<td>Greater than</td>
<td>Check which ingredient quantity is larger</td>
</tr>
<tr>
<td><code>&lt;</code></td>
<td>Less than</td>
<td>Check which ingredient quantity is smaller</td>
</tr>
<tr>
<td><code>&gt;=</code></td>
<td>Greater than or equal to</td>
<td>Check if an ingredient quantity is at least a certain amount</td>
</tr>
<tr>
<td><code>&lt;=</code></td>
<td>Less than or equal to</td>
<td>Check if an ingredient quantity is at most a certain amount</td>
</tr>
</tbody></table>
<h3>Example Code</h3>
<pre><code class="language-javascript">console.log(10 &gt; 5);    // true
console.log(4 &lt; 2);     // false
console.log(7 &gt;= 7);    // true
console.log(3 &lt;= 6);    // true

console.log(8 == "8");  // true
console.log(8 === "8"); // false

console.log(5 != 3);    // true
console.log(5 !== "5"); // true
</code></pre>
<h3>Important: <code>==</code> and <code>===</code> are not the same</h3>
<p>JavaScript has two operators for checking equality, and understanding their difference is extremely important.</p>
<p>The <code>==</code> operator checks if two values are equal, while ignoring their data types. In other words, it only cares about values, not the data types.</p>
<pre><code class="language-javascript">console.log(5 == 5);        // true     -&gt;     this makes sense
console.log(5 == "5");      // true     -&gt;     weird
</code></pre>
<p>If you've ever studied any other language, the above example might look weird. But the simple reason is, the <code>==</code> operator does not care about the data types.</p>
<p>On the other hand, the <code>===</code> operator does. It is called strict equality, and it checks both, values, as well as the data types.</p>
<pre><code class="language-javascript">console.log(5 === "5")    // false    -&gt;    now it makes sense
</code></pre>
<p>Think of <code>==</code> as a casual comparison, and <code>===</code> as a strict comparison.</p>
<h3>Recommendation</h3>
<p>In most cases, prefer using <code>===</code> instead of <code>==</code>. It avoids unexpected type conversions, and makes code more predictable in general.</p>
<hr />
<h2>Logical Operators</h2>
<p>Logical operators represent decisions the chef makes before cooking.</p>
<table>
<thead>
<tr>
<th>Operator</th>
<th>Meaning</th>
<th>Analogy</th>
</tr>
</thead>
<tbody><tr>
<td><code>&amp;&amp;</code></td>
<td>Logical AND</td>
<td>Cook the dish only if all ingredients are available</td>
</tr>
<tr>
<td><code>||</code></td>
<td>Logical OR</td>
<td>Cook the dish if atleast one ingredient is available</td>
</tr>
<tr>
<td><code>!</code></td>
<td>Logical NOT</td>
<td>Check if an ingredient is not available</td>
</tr>
</tbody></table>
<p>Just like Comparison operators, Logical operators also return boolean values. They help us combine multiple conditions together.</p>
<h3>Example Code</h3>
<pre><code class="language-javascript">let hasFlour = true;
let hasSugar = false;

console.log(hasFlour &amp;&amp; hasSugar);  // false
console.log(hasFlour || hasSugar);  // true
console.log(!hasFlour);             // false
</code></pre>
<h3>Truth Tables</h3>
<p>Truth Tables simply allow us to look at all the possible outputs that a logical operator can produce based on the inputs.</p>
<h3>Truth Table for Logical AND</h3>
<table>
<thead>
<tr>
<th>Input <code>A</code></th>
<th>Input <code>B</code></th>
<th><code>A &amp;&amp; B</code></th>
</tr>
</thead>
<tbody><tr>
<td>true</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>true</td>
<td>false</td>
<td>false</td>
</tr>
<tr>
<td>false</td>
<td>true</td>
<td>false</td>
</tr>
<tr>
<td>false</td>
<td>false</td>
<td>false</td>
</tr>
</tbody></table>
<p>It evaluates to <code>true</code>, only if both inputs are <code>true</code>. In all the other cases, it evaluates to <code>false</code>.</p>
<h3>Truth Table for Logical OR</h3>
<table>
<thead>
<tr>
<th>Input <code>A</code></th>
<th>Input <code>B</code></th>
<th><code>A || B</code></th>
</tr>
</thead>
<tbody><tr>
<td>true</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>true</td>
<td>false</td>
<td>true</td>
</tr>
<tr>
<td>false</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>false</td>
<td>false</td>
<td>false</td>
</tr>
</tbody></table>
<p>It evaluates to <code>false</code>, only if both inputs are <code>false</code>. In all the other cases, it evaluates to <code>true</code>.</p>
<h3>Truth Table for Logical NOT</h3>
<table>
<thead>
<tr>
<th>Input <code>A</code></th>
<th><code>!A</code></th>
</tr>
</thead>
<tbody><tr>
<td>true</td>
<td>false</td>
</tr>
<tr>
<td>false</td>
<td>true</td>
</tr>
</tbody></table>
<p>It simply flips the value. <code>true</code> becomes <code>false</code>, and <code>false</code> becomes <code>true</code>.</p>
<hr />
<h2>Assignment Operators</h2>
<p>Assignment operators are simply used to store values in variables and update them later. In assignment operators, we have the simple <code>=</code> assignment operator, that assigns the value on the right-hand side, to the variable on the left-hand side.</p>
<p>However in addition to this, we also have several compound assignment operators. These include <code>+=</code>, <code>-=</code>, <code>*=</code>, etc. These are just shorthands for longer assignment statements. In other words, <code>a += 5</code> is the same as <code>a = a + 5</code>.</p>
<p>As per our analogy, think of assignment operators like writing ingredients on a recipe board and modifying them as you cook.</p>
<table>
<thead>
<tr>
<th>Operator</th>
<th>Meaning</th>
<th>Analogy</th>
</tr>
</thead>
<tbody><tr>
<td><code>=</code></td>
<td>Assignment</td>
<td>Write an ingredient on the recipe board</td>
</tr>
<tr>
<td><code>+=</code></td>
<td>Add and assign</td>
<td>Add more of an ingredient to the recipe</td>
</tr>
<tr>
<td><code>-=</code></td>
<td>Subtract and assign</td>
<td>Remove some quantity of an ingredient</td>
</tr>
<tr>
<td><code>*=</code></td>
<td>Multiply and assign</td>
<td>Increase the recipe quantity multiple times</td>
</tr>
<tr>
<td><code>/=</code></td>
<td>Divide and assign</td>
<td>Split the ingredient quantity</td>
</tr>
<tr>
<td><code>%=</code></td>
<td>Modulus and assign</td>
<td>Store the leftover quantity</td>
</tr>
<tr>
<td><code>**=</code></td>
<td>Exponentiation and assign</td>
<td>Multiply the ingredient by itself multiple times</td>
</tr>
</tbody></table>
<h3>Example Code</h3>
<pre><code class="language-javascript">let quantity = 4;
console.log(quantity);      // 4

quantity += 3;
console.log(quantity);      // 7

quantity -= 2;
console.log(quantity);      // 5

quantity *= 2;
console.log(quantity);      // 10

quantity /= 5;
console.log(quantity);      // 2

quantity %= 2;
console.log(quantity);      // 0

quantity = 3;
quantity **= 2;
console.log(quantity);      // 9
</code></pre>
<hr />
<h2>Conditional/Ternary Operator</h2>
<p>The conditional (ternary) operator is a shorter way to write simple <code>if...else</code> conditions. It chooses between two values based on whether a condition is true or false.</p>
<pre><code class="language-javascript">condition ? valueIfTrue : valueIfFalse
</code></pre>
<p>As per our analogy, you can think of it as choosing between two dishes based on available ingredients. If chocolate is available, make a chocolate cake, otherwise make a vanilla cake.</p>
<h3>Example Code</h3>
<pre><code class="language-javascript">let age = 18;

let message = age &gt;= 18 ? "You can enter" : "Entry not allowed";

console.log(message);   // You can enter
</code></pre>
<hr />
<h2>Conclusion</h2>
<p>JavaScript operators are the building blocks that allow us to perform calculations, compare values and make decisions in our programs. We looked at some of the most popular operators in this article, such as the conditional operator, arithmetic, comparison, logical, and assignment.</p>
<p>You will eventually feel more at ease utilizing operators in real-world code if you continue experimenting with small examples and try combining various operators.</p>
]]></content:encoded></item><item><title><![CDATA[Promise Utility & Concurrency Methods: A Goa Trip Story]]></title><description><![CDATA[Introduction: A Trip to Goa
Imagine you're at that classic point in your life, where you try to plan a trip to Goa with your friends. We all know the ultimate output of such plans, don't we? 👀 Howeve]]></description><link>https://blog.sameerbhagtani.dev/promise-utility-and-concurrency-methods</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/promise-utility-and-concurrency-methods</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[promises]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Sun, 01 Mar 2026 10:31:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/695033c2b374c95f620094a1/ba20fbab-74c0-46a4-a05b-3b17968d7463.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction: A Trip to Goa</h2>
<p>Imagine you're at that classic point in your life, where you try to plan a trip to Goa with your friends. We all know the ultimate output of such plans, don't we? 👀 However, we still try with the dream of finally having a trip like "Zindagi Na Milegi Dobara".</p>
<img src="https://media1.tenor.com/m/n3_jCCC4AdUAAAAC/rock-chick-dance.gif" alt="" style="display:block;margin:0 auto" />

<p>So imagine you're the guy who's reaching out to everyone in your group, trying to finalize a trip to Goa. Let's explore various Promise Utility and Concurrency Methods in JavaScript from this lens 🧐, and trust me, you'll never forget them!</p>
<p>Think of Promises like waiting for your friends to confirm a trip. Each friend’s reply is uncertain. The different Promise methods simply define how strict you want to be about who joins the trip.</p>
<h2>Promise States: Your Friends' Replies</h2>
<p>Before we deep dive into Promise Utility and Concurrency Methods, let's take a quick look at the different states a promise can be in. These states are like the replies your friends can give you in our analogy. There are primarily 3 states:</p>
<h3>✅ Fulfilled</h3>
<p>The <code>fulfilled</code> state denotes successful completion of a Promise. It's like your friend saying "yes" to go on the trip with you (sounds dreamy, right? 😵‍💫).</p>
<h3>❌ Rejected</h3>
<p>The <code>rejected</code> state denotes failure in fulfilling a Promise. Thus, you must have guessed it, it's just like your friend saying "no" to the trip.</p>
<h3>⏳ Pending</h3>
<p>Now we all know that one friend, who knows that he doesn't wanna come, but is too shy to tell that to you. Such friends won't say either "yes" or "no", and will simply try to delay the talk.</p>
<p>The <code>pending</code> state is just like that! It's the state the promise remains in until it gets finally resolved (meaning <code>fulfilled</code> or <code>rejected</code>).</p>
<h2>Utility Methods</h2>
<h3><code>Promise.resolve()</code></h3>
<p>So let's say you start calling your friends up one by one asking about the trip. Now in order to boost your confidence, you firstly reach out to your friend "Rahul" who has the following characteristics:</p>
<ul>
<li><p>Chill parents</p>
</li>
<li><p>A lot of money (Like really a lot)</p>
</li>
<li><p>Always ready for anything</p>
</li>
</ul>
<p>You absolutely know that this is my guy. He never says "no" to anything. And that is what happens! He replies immediately with:</p>
<blockquote>
<p>"Bro I'm in."</p>
</blockquote>
<p>No waiting at all.</p>
<p>Me after Rahul's reply:</p>
<img src="https://media1.tenor.com/m/AGOS7ooBUxwAAAAC/yes.gif" alt="" style="display:block;margin:0 auto" />

<p>Example Code:</p>
<pre><code class="language-javascript">const askRahul = Promise.resolve("Rahul Confirmed");

askRahul.then((data) =&gt; console.log(data));
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">Rahul Confirmed
</code></pre>
<h3><code>Promise.reject()</code></h3>
<p>After you feel a boost in your confidence, you decide to go straight to the final boss, your friend "Kunal". Kunal has a great track record. Out of all the trips your friends group has taken, Kunal has agreed to come onto one, because it was a short one-day trip 🙄. For all the other occasions, Kunal always has excuses like:</p>
<blockquote>
<p>"Bro I have my exams"</p>
</blockquote>
<blockquote>
<p>"Bro my parents are not allowing"</p>
</blockquote>
<img src="https://media1.tenor.com/m/As3k9fH7xlsAAAAC/excuse-me.gif" alt="" style="display:block;margin:0 auto" />

<p>You hit him up, and just like always, he replies with immediate rejection.</p>
<p>Example Code:</p>
<pre><code class="language-javascript">const askKunal = Promise.reject("Kunal busy (like always)");

askKunal
    .then((data) =&gt; {
        console.log("This block of code never gets executed");
    })
    .catch((data) =&gt; {
        console.log(data);
    });
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">Kunal busy (like always)
</code></pre>
<h2>Concurrency Methods</h2>
<h3><code>Promise.all()</code></h3>
<p>This method takes an iterable of promises as input, and returns a single Promise. This returned promise gets <code>fulfilled</code> only if all of the input promises fulfill. It gets <code>rejected</code> even if any one input promise rejects.</p>
<p>In our analogy, this method is like the scenario:</p>
<blockquote>
<p>"Trip happens only if EVERYONE agrees"</p>
</blockquote>
<p>Let's say you ask three of your friends: Rahul, Kunal and Dev. We go on a trip only if everyone agrees. If even one friend cancels, the trip is cancelled.</p>
<p>Example Code:</p>
<pre><code class="language-javascript">const askEveryone = Promise.all([askRahul, askKunal, askDev]);

askEveryone
    .then((data) =&gt; {
        console.log("Yo everyone said 'yes'!");
        console.log(data.join("\n"));
    })
    .catch((data) =&gt; {
        console.log("We can't go! Someone said 'no'.");
        console.log(data);
    });
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">We can't go! Someone said 'no'.
Kunal busy (like always)
</code></pre>
<p>Kunal be like:</p>
<img src="https://media1.tenor.com/m/A34jnj3dRIAAAAAC/sherlock-holmes.gif" alt="" style="display:block;margin:0 auto" />

<h3><code>Promise.allSettled()</code></h3>
<p>This method takes an iterable of promises as input and returns a single Promise. This returned promise gets <code>fulfilled</code> simply when all of the input promises get completed. It doesn't matter whether they get <code>fulfilled</code>, or <code>rejected</code>. As long as all the input promises come out of their <code>pending</code> state, the returned promise of this method gets fulfilled.</p>
<p>In our analogy, this is like:</p>
<blockquote>
<p>"Let’s see everyone’s status first"</p>
</blockquote>
<p>You basically wanna see how many of your friends are agreeing to come, and how many or not. You don't cancel the trip automatically. You simply gather everyone's replies. You want a full report like this:</p>
<ul>
<li><p>Rahul -&gt; coming</p>
</li>
<li><p>Kunal -&gt; busy</p>
</li>
<li><p>Dev -&gt; coming</p>
</li>
</ul>
<p>Example Code:</p>
<pre><code class="language-javascript">const askEveryone = Promise.allSettled([askRahul, askKunal, askDev]);

askEveryone
    .then((data) =&gt; {
        console.log("Here is what everyone said:\n");
        console.log(data);
    })
    .catch((err) =&gt; {
        console.log(err);
    });
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">Here is what everyone said:

[
  { status: 'fulfilled', value: 'Rahul Confirmed' },
  { status: 'rejected', reason: 'Kunal busy (like always)' },
  { status: 'fulfilled', value: 'Dev Confirmed' }
]
</code></pre>
<h3><code>Promise.race()</code></h3>
<p>This method takes an iterable of promises as input and returns a single Promise. The returned promise gets settled with the eventual state of the first promise that settles.</p>
<p>The definition may sound a bit complex, but it really isn't. In our analogy, this is basically like:</p>
<blockquote>
<p>"We go with whoever replies first"</p>
</blockquote>
<p>If the first person says "Let's go!", then the trip happens. However, if the first person says "I can't come", the trip is immediately cancelled.</p>
<p>Example Code:</p>
<pre><code class="language-javascript">const askEveryone = Promise.race([askRahul, askKunal, askDev]);

askEveryone
    .then((data) =&gt; {
        console.log("First Person agreed:");
        console.log(data);
    })
    .catch((data) =&gt; {
        console.log("First Person denied:");
        console.log(data);
    });
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">First Person agreed:
Rahul Confirmed
</code></pre>
<p>In this example, Kunal again tries to disagree:</p>
<img src="https://scontent.famd5-3.fna.fbcdn.net/v/t39.30808-6/558094054_10161931449494080_210223962955399254_n.jpg?stp=dst-jpg_p526x296_tt6&amp;_nc_cat=107&amp;ccb=1-7&amp;_nc_sid=e06c5d&amp;_nc_ohc=OqBx5EeA-X8Q7kNvwHRQY78&amp;_nc_oc=AdksuUqIMBORvCrQmebLUFN06_EpT-6rfFkSRPepBj8tiEfVe6We8AHP7fb_wZLzJGs&amp;_nc_zt=23&amp;_nc_ht=scontent.famd5-3.fna&amp;_nc_gid=kVWCB0AL_w8XvDlpD6oP7w&amp;_nc_ss=8&amp;oh=00_AfuvOUTQ6nxxjMSenEzdrf6mDFRdhI10N1EPKM6BPLW03Q&amp;oe=69A9E4AA" alt="" style="display:block;margin:0 auto" />

<p>But Rahul is already on you're side, and thus the trip is on! 😎</p>
<h3>Promise.any()</h3>
<p>This method also takes an iterable of promises as input and returns a single Promise. The returned promise gets <code>fulfilled</code> when any one input promise gets <code>fulfilled</code>. It gets <code>rejected</code> if all of the input promises get <code>rejected</code>.</p>
<p>In our analogy, this is simple like:</p>
<blockquote>
<p>"We go as long as at least ONE friend can come"</p>
</blockquote>
<p>So you can imagine this as the final desperate situation in your trip planning. You're so tired of your friends just saying "no" every time, that this time you're simply ready to go even if one single friend "agrees". However, if you have really bad luck, and everyone says "no", the trip gets cancelled, and you realize ZNMD is just a hypothetical movie.</p>
<p>Example Code:</p>
<pre><code class="language-javascript">const askEveryone = Promise.any([askRahul, askKunal, askDev]);

askEveryone
    .then((data) =&gt; {
        console.log("One Person agreed:");
        console.log(data);
    })
    .catch((data) =&gt; {
        console.log("Everyone denied:");
        console.log(data);
    });
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">One Person agreed:
Rahul Confirmed
</code></pre>
<h2>Summary Table</h2>
<table>
<thead>
<tr>
<th>Method</th>
<th>Analogy</th>
</tr>
</thead>
<tbody><tr>
<td>resolve</td>
<td>Friend instantly agrees</td>
</tr>
<tr>
<td>reject</td>
<td>Friend instantly denies</td>
</tr>
<tr>
<td>all</td>
<td>Everyone must agree</td>
</tr>
<tr>
<td>allSettled</td>
<td>Show me everyone’s status</td>
</tr>
<tr>
<td>race</td>
<td>First reply decides</td>
</tr>
<tr>
<td>any</td>
<td>First agreement decides</td>
</tr>
</tbody></table>
<h2>Conclusion</h2>
<p>With this fun analogy, I don't think you will ever forget the different Promise methods. Planning a trip to Goa with your friends and working with Promises in JavaScript have something in common - uncertainty. You never know who will say “yes,” who will say “no,” or who will keep you waiting.</p>
<img src="https://i.pinimg.com/736x/de/ae/89/deae89bd889ad5052f543a4f296454c9.jpg" alt="" style="display:block;margin:0 auto" />

<p>Whether you need everyone to agree (<code>Promise.all</code>), just one person to say yes (<code>Promise.any</code>), the first reply (<code>Promise.race</code>), or a complete status report (<code>Promise.allSettled</code>), JavaScript gives you precise control over asynchronous flow.</p>
<p>And just like Goa plans, sometimes everything works out perfectly… and sometimes Kunal ruins it.</p>
]]></content:encoded></item><item><title><![CDATA[Inside the Browser: From URL to Pixels]]></title><description><![CDATA[Introduction
What happens after you type a URL and press Enter?
It feels instant, almost magical. One moment you see a blank tab, the next you’re looking at a fully styled webpage with text, images, b]]></description><link>https://blog.sameerbhagtani.dev/inside-the-browser</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/inside-the-browser</guid><category><![CDATA[internet]]></category><category><![CDATA[networking]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Browsers]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Fri, 30 Jan 2026 15:11:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769881467711/4ee12a7f-f68e-4244-b290-f05b62d06911.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>What happens after you type a URL and press Enter?</p>
<p>It feels instant, almost magical. One moment you see a blank tab, the next you’re looking at a fully styled webpage with text, images, buttons, and animations.</p>
<p>Behind the scenes, your browser is doing a surprising amount of work. It’s not just “opening a website”; it’s coordinating multiple components that fetch data, understand code, build structures, and finally paint pixels on your screen.</p>
<p>Let’s walk through that journey as a simple story of many small parts working together.</p>
<hr />
<h2>What a Browser Actually Is</h2>
<p>A browser is like a mini operating system dedicated to the web. Instead of running apps, it:</p>
<ul>
<li><p>Downloads web files (HTML, CSS, JavaScript, images)</p>
</li>
<li><p>Understands what those files mean</p>
</li>
<li><p>Decides how everything should look</p>
</li>
<li><p>Draws the final result on your screen</p>
</li>
<li><p>Reacts to your clicks, typing, and scrolling</p>
</li>
</ul>
<p>Think of it as a factory that takes raw materials (code) and turns them into a finished product (a visible, interactive webpage).</p>
<hr />
<h2>Components of a Browser</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769791698767/f6fe486f-4319-4a93-8c25-faf1a2cf9789.png" alt="" style="display:block;margin:0 auto" />

<p>At a very high level, a browser has a few key workers:</p>
<ol>
<li><p>User Interface: what you see and interact with</p>
</li>
<li><p>Browser Engine: the coordinator that tells others what to do</p>
</li>
<li><p>Rendering Engine: turns HTML/CSS into visual pixels</p>
</li>
<li><p>Networking: downloads files from the internet</p>
</li>
<li><p>JavaScript Engine: runs JavaScript code</p>
</li>
</ol>
<p>These parts act like departments in a company, each with a clear role but constantly talking to each other.</p>
<hr />
<h2>User Interface: Address Bar, Tabs, Buttons</h2>
<p>This is the visible shell of the browser:</p>
<ul>
<li><p>Address bar where you type URLs</p>
</li>
<li><p>Back/forward buttons</p>
</li>
<li><p>Tabs</p>
</li>
<li><p>Bookmarks bar</p>
</li>
</ul>
<p>When you press Enter after typing a URL, the UI passes that request inward to the rest of the browser machinery. From this point on, the real behind-the-scenes work begins.</p>
<hr />
<h2>Browser Engine vs Rendering Engine</h2>
<p>Browser engine is the manager, whereas Rendering Engine is the painter and the builder.</p>
<p>The browser engine:</p>
<ul>
<li><p>Receives your navigation request</p>
</li>
<li><p>Asks the networking part to fetch data</p>
</li>
<li><p>Tells the rendering engine to start building the page</p>
</li>
</ul>
<p>The rendering engine:</p>
<ul>
<li><p>Understands HTML and CSS</p>
</li>
<li><p>Figures out structure and style</p>
</li>
<li><p>Draws the page on the screen</p>
</li>
</ul>
<p>Manager decides what should happen. Painter decides what you see.</p>
<hr />
<h2>Networking: Fetching HTML, CSS, JS</h2>
<p>After you press Enter:</p>
<ol>
<li><p>The browser sends a request to the server.</p>
</li>
<li><p>The server responds with HTML (and links to CSS, JS, images, etc.).</p>
</li>
<li><p>The browser keeps requesting those extra files as it discovers them.</p>
</li>
</ol>
<p>This is like ordering a book online, then separately ordering its illustrations, cover design, and index as you realize they’re needed.</p>
<hr />
<h2>HTML Parsing and DOM Creation</h2>
<p>The HTML file is just text. The browser reads it and builds a structure called the DOM (Document Object Model).</p>
<p>For the following HTML:</p>
<pre><code class="language-xml">&lt;body&gt;
  &lt;h1&gt;Hello&lt;/h1&gt;
  &lt;p&gt;World&lt;/p&gt;
&lt;/body&gt;
</code></pre>
<p>A tree is created that looks like:</p>
<pre><code class="language-plaintext">   body
   /  \
 h1    p
</code></pre>
<p>This tree (the DOM) represents the structure and content of the page.</p>
<hr />
<h2>CSS Parsing and CSSOM Creation</h2>
<p>CSS is also read and converted into another tree-like structure called the CSSOM.</p>
<ul>
<li><p>If the DOM is: “What elements exist?”</p>
</li>
<li><p>The CSSOM is: “How should each element look?”</p>
</li>
</ul>
<p>For example:</p>
<pre><code class="language-css">h1 { color: red; }
</code></pre>
<p>The CSSOM records that all <code>h1</code> nodes should be red.</p>
<hr />
<h2>How DOM and CSSOM Come Together</h2>
<p>The browser combines:</p>
<ul>
<li><p>The DOM (structure)</p>
</li>
<li><p>The CSSOM (styles)</p>
</li>
</ul>
<p>to create a new structure often called the render tree. This render tree contains only what is actually visible and how it should appear. It’s like taking a skeleton (DOM) and putting clothes and colors on it (CSSOM).</p>
<hr />
<h2>Layout (Reflow), Painting, and Display</h2>
<p>Now the browser figures out geometry:</p>
<ol>
<li><p>Layout (Reflow)</p>
<ul>
<li><p>Where is each element?</p>
</li>
<li><p>How big is it?</p>
</li>
</ul>
</li>
<li><p>Painting</p>
<ul>
<li>Fill in colors, borders, text, shadows</li>
</ul>
</li>
<li><p>Display (Compositing)</p>
<ul>
<li>Put all painted pieces together and show them on the screen</li>
</ul>
</li>
</ol>
<p>This is the moment pixels finally appear and you see the webpage. If something changes (like resizing the window), layout and painting may run again.</p>
<hr />
<h2>The Entire Flow</h2>
<ol>
<li><p>You type a URL and press Enter.</p>
</li>
<li><p>Networking downloads HTML.</p>
</li>
<li><p>HTML is parsed → DOM is built.</p>
</li>
<li><p>CSS is downloaded and parsed → CSSOM is built.</p>
</li>
<li><p>DOM + CSSOM → render tree.</p>
</li>
<li><p>Layout calculates positions and sizes.</p>
</li>
<li><p>Painting fills in pixels.</p>
</li>
<li><p>The final page appears on your screen.</p>
</li>
</ol>
<p>Many of these steps can overlap and repeat as new resources arrive.</p>
<hr />
<h2>Conclusion</h2>
<p>A browser is not a single tool but a team of specialized components working in sequence. From fetching files to building trees, from calculating layouts to painting pixels, every webpage you open is the result of a carefully choreographed process.</p>
<p>And as a beginner, that’s all you need to grasp for now: not every tiny detail, but the beautiful flow from URL to pixels.</p>
]]></content:encoded></item><item><title><![CDATA[TCP vs UDP: Choosing the Right Transport]]></title><description><![CDATA[Introduction
The internet is basically a huge network of computers constantly sending tiny chunks of data to each other. But without rules, this data would arrive out of order, get lost, or collide wi]]></description><link>https://blog.sameerbhagtani.dev/tcp-vs-udp</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/tcp-vs-udp</guid><category><![CDATA[internet]]></category><category><![CDATA[networking]]></category><category><![CDATA[TCP]]></category><category><![CDATA[UDP]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Fri, 30 Jan 2026 15:08:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769877694258/2699f832-122d-4f4b-8576-58413af9cc66.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>The internet is basically a huge network of computers constantly sending tiny chunks of data to each other. But without rules, this data would arrive out of order, get lost, or collide with other data. To prevent chaos, the internet relies on well-defined communication rules called protocols.</p>
<p>Two of the most important of these rules are TCP and UDP. They decide how data is sent from one machine to another. On top of them, higher-level rules like HTTP define what that data means (like a web page or API response).</p>
<p>To understand modern networking and backend systems, you need to know when to use TCP, when to use UDP, and how HTTP fits into the picture.</p>
<hr />
<h2>What are TCP and UDP?</h2>
<p>Think of sending data like sending messages in the real world.</p>
<ul>
<li><p><strong>TCP (Transmission Control Protocol)</strong> is like a phone call. You establish a connection, talk carefully, confirm every message is heard, and hang up only when done.</p>
</li>
<li><p><strong>UDP (User Datagram Protocol)</strong> is like making an announcement on a loudspeaker. You just broadcast your message. No one confirms receipt. It’s fast, but some people might miss parts of it.</p>
</li>
</ul>
<p>Both are transport protocols. Their job is to move raw data between two computers over the internet.</p>
<hr />
<h2>Key Differences Between TCP and UDP</h2>
<table>
<thead>
<tr>
<th><strong>Feature</strong></th>
<th><strong>TCP</strong></th>
<th><strong>UDP</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Reliability</td>
<td>Guaranteed delivery</td>
<td>No guarantee</td>
</tr>
<tr>
<td>Order</td>
<td>Data arrives in correct order</td>
<td>May arrive out of order</td>
</tr>
<tr>
<td>Error checking</td>
<td>Yes, with retransmission</td>
<td>Minimal</td>
</tr>
<tr>
<td>Speed</td>
<td>Slower (extra safety steps)</td>
<td>Faster (no safety overhead)</td>
</tr>
<tr>
<td>Connection</td>
<td>Connection-based</td>
<td>Connectionless</td>
</tr>
</tbody></table>
<p>In short,</p>
<ul>
<li><p>TCP = safe and reliable</p>
</li>
<li><p>UDP = fast but risky</p>
</li>
</ul>
<hr />
<h2>When to Use TCP</h2>
<p>Use TCP when correctness matters more than speed. Examples:</p>
<ul>
<li><p>Loading a website</p>
</li>
<li><p>Sending emails</p>
</li>
<li><p>Downloading files</p>
</li>
<li><p>API requests and database queries</p>
</li>
</ul>
<p>TCP is like a courier service that tracks every package and resends it if lost. You might wait a bit longer, but you’ll get everything intact. If even one missing or out-of-order piece breaks your data, choose TCP.</p>
<hr />
<h2>When to Use UDP</h2>
<p>Use UDP when speed matters more than perfection. Examples:</p>
<ul>
<li><p>Live video streaming</p>
</li>
<li><p>Online gaming</p>
</li>
<li><p>Voice/video calls</p>
</li>
<li><p>Real-time sensor data</p>
</li>
</ul>
<p>UDP is like a live TV broadcast. If a few frames drop, the show keeps going. Waiting to “fix” the missing frame would cause annoying lag. If a small loss is acceptable but delays are not, choose UDP.</p>
<hr />
<h2>Common Real-World Examples</h2>
<h3>TCP-based</h3>
<ul>
<li><p>Web browsing (HTTP/HTTPS)</p>
</li>
<li><p>File transfer (FTP, SFTP)</p>
</li>
<li><p>SSH remote login</p>
</li>
<li><p>Email (SMTP, IMAP)</p>
</li>
</ul>
<h3>UDP-based</h3>
<ul>
<li><p>DNS lookups</p>
</li>
<li><p>Video conferencing</p>
</li>
<li><p>Online multiplayer games</p>
</li>
<li><p>Live streaming protocols</p>
</li>
</ul>
<p>Notice the pattern:</p>
<ul>
<li><p>Important, structured data → TCP</p>
</li>
<li><p>Real-time, continuous data → UDP</p>
</li>
</ul>
<hr />
<h2>What is HTTP and Where It Fits</h2>
<p>HTTP (HyperText Transfer Protocol) is the language your browser and servers use to talk about web content. It defines things like:</p>
<ul>
<li><p>“GET this page”</p>
</li>
<li><p>“POST this form data”</p>
</li>
<li><p>Status codes like 200, 404, 500</p>
</li>
</ul>
<p>But HTTP does not decide how the data physically travels across the network. It only defines the format and meaning of the messages. HTTP is an application-layer protocol.</p>
<hr />
<h2>Relationship Between TCP and HTTP</h2>
<p>HTTP rides on top of TCP.</p>
<p>Layering looks like this:</p>
<pre><code class="language-plaintext">HTTP -&gt; TCP -&gt; IP -&gt; Network
</code></pre>
<ul>
<li><p>HTTP says what to send (requests and responses)</p>
</li>
<li><p>TCP ensures it is delivered correctly and in order</p>
</li>
</ul>
<p>HTTP does not replace TCP. HTTP uses TCP to get reliability. Without TCP, HTTP messages could arrive broken or shuffled. Without HTTP, TCP would just be sending meaningless bytes.</p>
<hr />
<h2>Conclusion</h2>
<p>The internet needs rules to move data safely and efficiently. TCP and UDP are two different strategies for that job:</p>
<ul>
<li><p>TCP is careful, reliable, and ordered.</p>
</li>
<li><p>UDP is fast, lightweight, and best for real-time use.</p>
</li>
</ul>
<p>HTTP sits above them, describing web requests and responses, while relying on TCP to ensure those messages arrive perfectly.</p>
]]></content:encoded></item><item><title><![CDATA[TCP Made Simple: Handshake to Reliability]]></title><description><![CDATA[Introduction
Imagine two people trying to talk on a phone call without saying “hello” first, without taking turns, and without confirming what they heard. Messages would overlap, get lost, or be misun]]></description><link>https://blog.sameerbhagtani.dev/tcp-made-simple</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/tcp-made-simple</guid><category><![CDATA[internet]]></category><category><![CDATA[networking]]></category><category><![CDATA[TCP]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Fri, 30 Jan 2026 15:00:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769877826616/331a5fa7-eef9-4713-8675-de0ed4e3e474.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Imagine two people trying to talk on a phone call without saying “hello” first, without taking turns, and without confirming what they heard. Messages would overlap, get lost, or be misunderstood.</p>
<p>Computer networks face the same problem. If devices just threw data at each other without any rules, communication would quickly become messy and unreliable.</p>
<p>This is where TCP comes in. It adds discipline, structure, and confirmation to network communication so that data arrives safely, in order, and without corruption.</p>
<hr />
<h2>What is TCP and Why It Is Needed</h2>
<p>TCP (Transmission Control Protocol) is a set of rules that devices use to send data reliably over a network. When you load a website, send an email, or download a file, TCP is usually working behind the scenes to make sure:</p>
<ul>
<li><p>No data is lost</p>
</li>
<li><p>Data arrives in the correct order</p>
</li>
<li><p>Errors are detected and fixed</p>
</li>
</ul>
<p>Without TCP, data would just be a stream of random pieces with no guarantee that the receiver gets the full message correctly.</p>
<hr />
<h2>Problems TCP Is Designed to Solve</h2>
<p>Sending data over the internet is not as clean as passing a note across a table. Along the way:</p>
<ul>
<li><p>Packets (chunks of data) can be lost</p>
</li>
<li><p>Packets can arrive out of order</p>
</li>
<li><p>Packets can get duplicated</p>
</li>
<li><p>Packets can be corrupted</p>
</li>
</ul>
<p>If we send data without any rules:</p>
<ul>
<li><p>The receiver won’t know what’s missing</p>
</li>
<li><p>It won’t know what came first</p>
</li>
<li><p>It won’t know if something is wrong</p>
</li>
</ul>
<p>TCP solves this by numbering data, asking for confirmations, and resending anything that goes missing.</p>
<hr />
<h2>What is the TCP 3-Way Handshake</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769793286122/98b12197-8ce0-4ca6-90b3-76e021b6b5ec.jpeg" alt="" style="display:block;margin:0 auto" />

<p>Before sending actual data, TCP first sets up a connection between the two devices. Think of it like starting a conversation:</p>
<ol>
<li><p>“Can we talk?”</p>
</li>
<li><p>“Yes, we can talk.”</p>
</li>
<li><p>“Great, let’s start.”</p>
</li>
</ol>
<p>This setup process is called the 3-way handshake. It makes sure both sides are ready and agree on some initial numbers used to track data.</p>
<hr />
<h2>Step-by-Step Working of SYN, SYN-ACK, and ACK</h2>
<ol>
<li><p>SYN (Synchronize): The client says: “I want to start a connection. Here’s my starting sequence number.”</p>
</li>
<li><p>SYN-ACK (Synchronize + Acknowledge): The server replies: “I got your request. Here’s my starting number, and I confirm yours.”</p>
</li>
<li><p>ACK (Acknowledge): The client responds: “I confirm your number too. Let’s begin.”</p>
</li>
</ol>
<p>After this, both sides trust each other and know where to start counting data from.</p>
<hr />
<h2>How Data Transfer Works in TCP</h2>
<p>Once connected, data is sent in small chunks. Each chunk has a sequence number.</p>
<p>Example idea:</p>
<ul>
<li><p>Chunk 1 → number 1</p>
</li>
<li><p>Chunk 2 → number 2</p>
</li>
<li><p>Chunk 3 → number 3</p>
</li>
</ul>
<p>The receiver sends back an acknowledgement (ACK) saying: “I have received everything up to number X.” If the sender doesn’t receive an ACK for some number, it assumes that chunk was lost and sends it again.</p>
<hr />
<h2>How TCP Ensures Reliability, Order, and Correctness</h2>
<p>TCP uses a few simple but powerful ideas:</p>
<ol>
<li><p>Sequence Numbers: Keep data in the correct order, even if packets arrive mixed up.</p>
</li>
<li><p>Acknowledgements: Confirm what has been successfully received.</p>
</li>
<li><p>Retransmission: If something isn’t acknowledged in time, resend it.</p>
</li>
<li><p>Error Checking: Each packet has a checksum. If data is corrupted, it is rejected and resent.</p>
</li>
</ol>
<p>So even if the network drops or scrambles packets, TCP rebuilds the correct message on the receiver’s side.</p>
<hr />
<h2>How TCP Handles Packet Loss</h2>
<p>Suppose packets 1, 2, 3 are sent. The receiver gets 1 and 3, but 2 is lost. The receiver will keep saying. “I’m still waiting for 2.” The sender sees that 2 is not being acknowledged and resends packet 2. Only after packet 2 arrives will the receiver move forward and acknowledge packet 3 and beyond.</p>
<p>This is how TCP avoids gaps in the final data.</p>
<hr />
<h2>How a TCP Connection Is Closed</h2>
<p>Ending a TCP connection is also a careful, confirmed process. It’s like saying goodbye properly instead of just hanging up.</p>
<ol>
<li><p>One side sends FIN: “I’m done sending data.”</p>
</li>
<li><p>Other side sends ACK: “Got it.”</p>
</li>
<li><p>Then the second side sends its own FIN: “I’m also done.”</p>
</li>
<li><p>First side sends final ACK: “Confirmed. Connection closed.”</p>
</li>
</ol>
<p>This ensures both sides finish cleanly without losing the last bits of data.</p>
<hr />
<h2>Conclusion</h2>
<p>TCP brings order to the chaos of network communication.</p>
<p>Through a simple handshake, numbered data, acknowledgements, and smart resending of lost pieces, it guarantees that what you send is exactly what the other side receives. Whether you’re loading a webpage or building your own backend server, TCP is the quiet workhorse that makes reliable communication possible.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Network Devices: How Data Travels Across the Internet]]></title><description><![CDATA[Introduction
Before your backend server handles an API request or your frontend loads a web page, data has to travel through a chain of physical network devices. These devices move bits across cities,]]></description><link>https://blog.sameerbhagtani.dev/understanding-network-devices</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/understanding-network-devices</guid><category><![CDATA[internet]]></category><category><![CDATA[networking]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[modem]]></category><category><![CDATA[router]]></category><category><![CDATA[firewall]]></category><category><![CDATA[Load Balancer]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Fri, 30 Jan 2026 14:56:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769877124197/e259bd81-a46f-4672-a73d-3e02920b2ca2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Before your backend server handles an API request or your frontend loads a web page, data has to travel through a chain of physical network devices. These devices move bits across cities, buildings, and rooms before your code ever runs.</p>
<p>Whether you’re in a home setup or a production data center, the journey from “the internet” to your machine always involves a few key players: modems, routers, switches, firewalls, and sometimes load balancers.</p>
<p>Understanding what each of these actually does gives you a clearer picture of how real-world systems are built and deployed.</p>
<p>Let’s start from the moment the internet line enters a building.</p>
<hr />
<h2>High-level journey: How the internet reaches your home or office</h2>
<ol>
<li><p>Your ISP sends internet signals through a cable (fiber, coax, DSL, etc.).</p>
</li>
<li><p>A modem converts those signals into usable digital data.</p>
</li>
<li><p>A router decides where that data should go.</p>
</li>
<li><p>A switch connects multiple local devices efficiently.</p>
</li>
<li><p>A firewall filters and protects traffic.</p>
</li>
<li><p>In bigger systems, a load balancer spreads traffic across many servers.</p>
</li>
</ol>
<p>Think of it like a logistics pipeline: incoming packages, sorting centers, traffic control, security checks, and distribution.</p>
<hr />
<h2>Modem</h2>
<p>A modem is the translator between your ISP and your local network.</p>
<p>Your internet provider sends data in a format suitable for long-distance transmission over cables. Your devices, however, understand standard digital Ethernet signals. The modem converts between these two worlds.</p>
<div>
<div>💡</div>
<div>Analogy: The modem is like a customs checkpoint at the country border. It converts foreign-format packages into something your local postal system understands.</div>
</div>

<hr />
<h2>Router</h2>
<p>A router is the traffic director of your network. It connects two networks:</p>
<ul>
<li><p>The outside internet (via the modem)</p>
</li>
<li><p>Your internal local network (phones, laptops, servers)</p>
</li>
</ul>
<p>When data comes in, the router decides which internal device should receive it. When your device sends data out, the router decides where on the internet to send it.</p>
<div>
<div>💡</div>
<div>Analogy: The router is like a traffic police officer at a busy junction, guiding each vehicle to the correct road.</div>
</div>

<p>Router ≠ Modem:</p>
<ul>
<li><p>Modem: brings internet in</p>
</li>
<li><p>Router: distributes it correctly</p>
</li>
</ul>
<hr />
<h2>Switch vs Hub</h2>
<p>Both connect many devices in a local network, but they behave very differently.</p>
<h3>Hub (old, dumb)</h3>
<p>A hub sends incoming data to every port.</p>
<div>
<div>💡</div>
<div>Analogy: Someone shouting a message to everyone in a room, even if only one person needs it.</div>
</div>

<p>Problems:</p>
<ul>
<li><p>Wastes bandwidth</p>
</li>
<li><p>Causes collisions</p>
</li>
<li><p>No intelligence</p>
</li>
</ul>
<h3>Switch (modern, smart)</h3>
<p>A switch learns which device is on which port and sends data only where needed.</p>
<div>
<div>💡</div>
<div>Analogy: A post office that looks at the address and delivers the letter to the correct house only.</div>
</div>

<p>Benefits:</p>
<ul>
<li><p>Faster communication</p>
</li>
<li><p>Better security</p>
</li>
<li><p>Efficient bandwidth usage</p>
</li>
</ul>
<p>Real networks use switches, not hubs.</p>
<hr />
<h2>Firewall</h2>
<ul>
<li>A firewall is the security gatekeeper. It inspects incoming and outgoing traffic and decides what is allowed or blocked based on rules.</li>
</ul>
<div>
<div>💡</div>
<div>Analogy: A security guard at a building entrance checking IDs before letting people in.</div>
</div>

<p>Typical rules:</p>
<ul>
<li><p>Allow web traffic (ports 80/443)</p>
</li>
<li><p>Block unknown inbound connections</p>
</li>
<li><p>Restrict access to internal services</p>
</li>
</ul>
<p>In small setups, the router often has a built-in firewall. In production systems, dedicated firewall appliances add stronger, more granular control.</p>
<hr />
<h2>Load Balancer</h2>
<p>A load balancer sits in front of multiple servers and spreads incoming requests among them.</p>
<p>Instead of:</p>
<pre><code class="language-plaintext">User -&gt; One Server
</code></pre>
<p>You get:</p>
<pre><code class="language-plaintext">User -&gt; Load Balancer -&gt; Many Servers
</code></pre>
<div>
<div>💡</div>
<div>Analogy: A toll booth with many lanes, directing each car to the least busy lane.</div>
</div>

<p>Benefits:</p>
<ul>
<li><p>Prevents overload on a single server</p>
</li>
<li><p>Improves availability</p>
</li>
<li><p>Enables horizontal scaling</p>
</li>
</ul>
<p>This is critical for backend systems serving thousands or millions of users.</p>
<hr />
<h2>Conclusion</h2>
<p>Network devices are the physical backbone that make the internet usable and scalable. The modem connects you to the world, the router directs traffic, the switch organizes local communication, the firewall protects your boundary, and the load balancer enables growth.</p>
]]></content:encoded></item><item><title><![CDATA[CSS Selectors 101: Targeting Elements with Precision]]></title><description><![CDATA[Introduction
When you write CSS, you’re not styling the whole page at once. You’re telling the browser exactly which elements should look a certain way. CSS selectors are the tools that let you point ]]></description><link>https://blog.sameerbhagtani.dev/css-selectors-101</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/css-selectors-101</guid><category><![CDATA[Web Development]]></category><category><![CDATA[CSS]]></category><category><![CDATA[CSS3]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Fri, 30 Jan 2026 14:16:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769882874074/e0126d92-238d-4775-b29f-e72ac5537428.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>When you write CSS, you’re not styling the whole page at once. You’re telling the browser exactly which elements should look a certain way. CSS selectors are the tools that let you point at specific elements and say, “You, change your color”, or “You, add some spacing.”</p>
<p>Think of selectors like addressing people in real life. You could say “Hey, everyone!” (very broad), or “Hey, people wearing red shirts!” (more specific), or “Hey, Rahul!” (very precise).</p>
<hr />
<h2>Why CSS Selectors are Needed?</h2>
<p>HTML gives structure to your page:</p>
<pre><code class="language-xml">&lt;h1&gt;Welcome&lt;/h1&gt;
&lt;p&gt;This is a paragraph.&lt;/p&gt;
&lt;p&gt;This is another paragraph.&lt;/p&gt;
</code></pre>
<p>But you use CSS to style your webpage. And without selectors, CSS wouldn’t know which elements to style.</p>
<p>If you write:</p>
<pre><code class="language-css">p {
    color: blue;
}
</code></pre>
<p>You’re telling the browser to select all the <code>&lt;p&gt;</code> elements and make their text blue. Selectors are simply ways to choose elements from your HTML so you can style them.</p>
<hr />
<h2>Types of CSS Selectors</h2>
<h3>Element Selector</h3>
<p>This is the simplest selector. It targets elements by their tag name.</p>
<ul>
<li>HTML:</li>
</ul>
<pre><code class="language-xml">&lt;p&gt;This is a paragraph.&lt;/p&gt;
&lt;p&gt;This is another paragraph.&lt;/p&gt;
</code></pre>
<ul>
<li>CSS:</li>
</ul>
<pre><code class="language-css">p {
    color: green;
}
</code></pre>
<p>Both paragraphs become green. Use this when you want to style every element of a certain type.</p>
<h3>Class Selector</h3>
<p>Classes let you target specific groups of elements.</p>
<ul>
<li>HTML:</li>
</ul>
<pre><code class="language-xml">&lt;p class="highlight"&gt;Important text&lt;/p&gt;
&lt;p&gt;Normal text&lt;/p&gt;
&lt;p class="highlight"&gt;Another important text&lt;/p&gt;
</code></pre>
<ul>
<li>CSS:</li>
</ul>
<pre><code class="language-css">.highlight {
    background-color: yellow;
}
</code></pre>
<p>Only the paragraphs with <code>class="highlight"</code> get a yellow background. Classes are reusable. Multiple elements can share the same class.</p>
<h3>ID Selector</h3>
<p>An ID is meant for a single, unique element.</p>
<ul>
<li>HTML:</li>
</ul>
<pre><code class="language-xml">&lt;h1 id="main-title"&gt;My Website&lt;/h1&gt;
&lt;h1&gt;Another heading&lt;/h1&gt;
</code></pre>
<ul>
<li>CSS:</li>
</ul>
<pre><code class="language-css">#main-title {
    color: red;
}
</code></pre>
<p>Only the first heading turns red. Use IDs when you want to style one unique element.</p>
<h3>Group Selectors</h3>
<p>Sometimes you want to apply the same style to multiple different elements.</p>
<ul>
<li>CSS:</li>
</ul>
<pre><code class="language-css">h1, p {
    font-family: Arial, sans-serif;
}
</code></pre>
<p>This selects all <code>&lt;h1&gt;</code> and all <code>&lt;p&gt;</code> elements. Grouping saves repetition and keeps your CSS clean.</p>
<h3>Descendant Selectors</h3>
<p>These target elements inside other elements.</p>
<ul>
<li>HTML:</li>
</ul>
<pre><code class="language-xml">&lt;div class="card"&gt;
  &lt;p&gt;This is inside the card.&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;This is outside the card.&lt;/p&gt;
</code></pre>
<ul>
<li>CSS:</li>
</ul>
<pre><code class="language-css">.card p {
    color: blue;
}
</code></pre>
<p>Only the paragraph inside <code>.card</code> becomes blue. The outside paragraph stays unchanged. You’re not selecting all paragraphs, only those that are descendants of <code>.card</code>.</p>
<hr />
<h2>Basic Selector Priority</h2>
<p>If multiple selectors target the same element, some have more power than others. A very high level rule is:</p>
<pre><code class="language-plaintext">ID &gt; Class &gt; Element
</code></pre>
<p>Example:</p>
<pre><code class="language-css">p {
  color: green;
}

.highlight {
  color: blue;
}

#main-text {
  color: red;
}
</code></pre>
<p>For:</p>
<pre><code class="language-xml">&lt;p id="main-text" class="highlight"&gt;Hello&lt;/p&gt;
</code></pre>
<p>Final color will be <strong>red</strong>, since the ID selector has more priority than element and class selectors. This priority system helps CSS decide which style to apply when there’s a conflict.</p>
<hr />
<h2>Conclusion</h2>
<p>CSS selectors are how you “address” elements in your webpage. From broad choices like all paragraphs, to precise targets like one unique ID, selectors give you full control over styling. Mastering selectors means mastering the foundation of CSS. Once you can precisely target elements, you can style anything with confidence.</p>
]]></content:encoded></item><item><title><![CDATA[HTML Tags & Elements: The Building Blocks of Every Webpage]]></title><description><![CDATA[Introduction
Every website you visit, from a simple blog to a complex web app, is built on one fundamental language: HTML. If CSS is the paint and JavaScript is the behavior, then HTML is the skeleton]]></description><link>https://blog.sameerbhagtani.dev/html-tags-and-elements</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/html-tags-and-elements</guid><category><![CDATA[Web Development]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[HTML]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Fri, 30 Jan 2026 13:58:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769884815565/a0f18cb7-a626-44b6-963f-aaf75e3c67d2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Every website you visit, from a simple blog to a complex web app, is built on one fundamental language: HTML. If CSS is the paint and JavaScript is the behavior, then HTML is the skeleton that gives the page its basic shape.</p>
<p>In this blog post, we’ll break down what HTML really is, what tags and elements mean, and how they work together to create the structure of a webpage.</p>
<hr />
<h2>What HTML Is and Why We Use It</h2>
<p>HTML stands for HyperText Markup Language. It is not a programming language, it’s a markup language used to structure content on the web.</p>
<p>Think of a webpage like a human body:</p>
<ul>
<li><p>HTML = skeleton (structure)</p>
</li>
<li><p>CSS = skin and clothes (appearance)</p>
</li>
<li><p>JavaScript = muscles and brain (behavior)</p>
</li>
</ul>
<p>Without HTML, a browser wouldn’t know what is a heading, what is a paragraph, what is an image, or what is a button. HTML gives meaning and structure to raw text and media.</p>
<hr />
<h2>Tags in HTML</h2>
<p>An HTML tag is a special keyword wrapped in angle brackets. Some examples are as below:</p>
<pre><code class="language-xml">&lt;p&gt;
&lt;h1&gt;
&lt;div&gt;
</code></pre>
<p>You can think of a tag like a label on a box. The label tells the browser what kind of content is inside that box. For example:</p>
<ul>
<li><p><code>&lt;p&gt;</code> says “this is a paragraph”</p>
</li>
<li><p><code>&lt;h1&gt;</code> says “this is the main heading”</p>
</li>
</ul>
<h3>Paired Tags(Container Tags)</h3>
<p>Most tags in HTML, require a corresponding closing tag too:</p>
<pre><code class="language-xml">&lt;p&gt;Hello World&lt;/p&gt;
</code></pre>
<p>Here:</p>
<ul>
<li><p><code>&lt;p&gt;</code> is the opening tag.</p>
</li>
<li><p><code>&lt;/p&gt;</code> is the closing tag.</p>
</li>
<li><p><code>Hello World</code> is the content.</p>
</li>
</ul>
<p>The closing tag has a <code>/</code> before the tag name. It tells the browser: “this part is over now”.</p>
<h3>Self-Closing (Void) Tags</h3>
<p>Some tags don’t have content and therefore don’t need a closing tag. Some examples are below:</p>
<pre><code class="language-xml">&lt;img src="image.jpg" alt="Image" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
</code></pre>
<p>It’s a good practice to have a <code>/</code> at the end for such tags.</p>
<hr />
<h2>Elements in HTML</h2>
<p>An HTML Element refers to the combination of an opening tag, closing tag, and the content in between. Example:</p>
<pre><code class="language-xml">&lt;h1&gt;Welcome&lt;/h1&gt;
</code></pre>
<p>Here, <code>&lt;h1&gt;</code> alone is a tag, however the entire line, <code>&lt;h1&gt;Welcome&lt;/h1&gt;</code>, is an element.</p>
<div>
<div>💡</div>
<div>In short, element = opening tag + content + closing tag.</div>
</div>

<hr />
<h2>Block-Level vs Inline Elements</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769781635251/cf98652d-dbea-4923-8076-2fc2ea69b4a1.webp" alt="" style="display:block;margin:0 auto" />

<h3>Block-level Elements</h3>
<p>Elements that always start on a new line and take full width by default are called Block-level elements. They behave like big boxes stacked vertically.</p>
<p>Examples:</p>
<pre><code class="language-xml">&lt;h1&gt;Heading&lt;/h1&gt;
&lt;p&gt;Paragraph&lt;/p&gt;
&lt;div&gt;Container&lt;/div&gt;
</code></pre>
<h3>Inline Elements</h3>
<p>Elements that always stay on the same line and only take up as much width as needed are called Inline elements. They behave like small pieces of text inside a line.</p>
<p>Examples:</p>
<pre><code class="language-xml">&lt;span&gt;Text&lt;/span&gt;
&lt;a href="#"&gt;Link&lt;/a&gt;
&lt;strong&gt;Bold&lt;/strong&gt;
</code></pre>
<hr />
<h2>Some Commonly Used HTML Tags</h2>
<table>
<thead>
<tr>
<th>Tag</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>&lt;h1&gt;...&lt;/h1&gt; to &lt;h6&gt;...&lt;/h6&gt;</code></td>
<td>Headings</td>
</tr>
<tr>
<td><code>&lt;p&gt;…&lt;/p&gt;</code></td>
<td>Paragraph</td>
</tr>
<tr>
<td><code>&lt;div&gt;…&lt;/div&gt;</code></td>
<td>Generic block container</td>
</tr>
<tr>
<td><code>&lt;span&gt;…&lt;/span&gt;</code></td>
<td>Generic inline container</td>
</tr>
<tr>
<td><code>&lt;a&gt;…&lt;/a&gt;</code></td>
<td>Link</td>
</tr>
<tr>
<td><code>&lt;img /&gt;</code></td>
<td>Image</td>
</tr>
<tr>
<td><code>&lt;ul&gt;…&lt;/ul&gt;</code></td>
<td>Unordered List</td>
</tr>
<tr>
<td><code>&lt;ol&gt;…&lt;/ol&gt;</code></td>
<td>Ordered List</td>
</tr>
<tr>
<td><code>&lt;li&gt;…&lt;/li&gt;</code></td>
<td>List item</td>
</tr>
<tr>
<td><code>&lt;br /&gt;</code></td>
<td>Line break</td>
</tr>
<tr>
<td><code>&lt;hr /&gt;</code></td>
<td>Horizontal rule</td>
</tr>
</tbody></table>
<hr />
<h2>Conclusion</h2>
<p>HTML is the foundation of every webpage. By using tags, we tell the browser what each piece of content represents, and by combining opening and closing tags, we create elements that form the structure of the page.</p>
<p>Once your HTML skeleton is solid, you can style it with CSS and bring it to life with JavaScript.</p>
]]></content:encoded></item><item><title><![CDATA[cURL Explained: Talk to the Internet from Your Terminal]]></title><description><![CDATA[Introduction
When you send a request to a server using cURL, the server doesn’t just send back data blindly. It returns a structured response that tells you what happened, what kind of data you got, a]]></description><link>https://blog.sameerbhagtani.dev/curl-explained</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/curl-explained</guid><category><![CDATA[Web Development]]></category><category><![CDATA[backend]]></category><category><![CDATA[networking]]></category><category><![CDATA[terminal]]></category><category><![CDATA[curl]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[server]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Fri, 30 Jan 2026 13:32:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769879974036/6398672e-9dec-49b9-979d-da88f96bdbb7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>When you send a request to a server using cURL, the server doesn’t just send back data blindly. It returns a structured response that tells you what happened, what kind of data you got, and the actual content itself. Understanding this response format is essential for debugging APIs and backend systems. Once you can read a response properly, you can quickly figure out why something works or fails.</p>
<hr />
<h2>What is cURL?</h2>
<p>cURL, which stands for “Client URL”, is a command line tool that lets you send and receive data over the internet. If your browser is a friendly graphical app that loads websites when you click links, cURL is the raw, text-based version of that idea. Instead of clicking buttons, you type commands in your terminal to make requests to servers and see their responses directly.</p>
<p>It’s a way to open a direct conversation between your computer and a web server. No UI, no buttons, just pure request and response.</p>
<hr />
<h2>Why programmers need cURL?</h2>
<p>When you’re doing backend development or working with APIs, you often need to:</p>
<ul>
<li><p>Test an API endpoint</p>
</li>
<li><p>Send data to a server</p>
</li>
<li><p>See exactly what the server returns</p>
</li>
<li><p>Debug why a request is failing</p>
</li>
</ul>
<p>Using a browser hides a lot of details. Using cURL shows you everything.</p>
<p>For example, when you build an API in your own server (like with Node/Express), you can instantly test it with cURL without writing any frontend code. It’s fast, lightweight, and perfect for Debugging, Automation scripts, etc.</p>
<hr />
<h2>Making your first request using cURL</h2>
<p>The simplest usage of cURL is:</p>
<pre><code class="language-bash">curl https://example.com
</code></pre>
<p>When you run the above command, the following happens:</p>
<ol>
<li><p>Your computer sends an HTTP <code>GET</code> request to <code>https://example.com</code></p>
</li>
<li><p>The server responds with some data (usually HTML)</p>
</li>
<li><p>cURL prints that raw response directly in your terminal</p>
</li>
</ol>
<p>You won’t see a rendered webpage like in a browser. You’ll see the actual HTML source.</p>
<div>
<div>💡</div>
<div>By default, <code>curl URL</code> sends a <code>GET</code> request to a URL and shows the response body.</div>
</div>

<hr />
<h2>Understanding Request</h2>
<p>Every web communication has two parts: Request and Response. Let’s explore Request first. It contains things like:</p>
<ul>
<li><p>Method (<code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>DELETE</code>, etc.)</p>
</li>
<li><p>URL</p>
</li>
<li><p>Headers</p>
</li>
<li><p>Optional body (data you send to the server)</p>
</li>
</ul>
<p>Example request in cURL:</p>
<pre><code class="language-bash">curl -X POST https://api.example.com/users
</code></pre>
<p>The <code>-X</code> flag allows you to define the HTTP method (<code>GET</code>, <code>POST</code>, etc.) for the request.</p>
<hr />
<h2>Understanding Response</h2>
<p>The server sends a response to your request which contains:</p>
<ul>
<li><p>Status code (like <code>200</code>, <code>404</code>, <code>500</code>)</p>
</li>
<li><p>Headers</p>
</li>
<li><p>Body (JSON, HTML, text, etc.)</p>
</li>
</ul>
<p>To see full details including headers, use:</p>
<pre><code class="language-bash">curl -i https://example.com
</code></pre>
<p>The output will look something like this:</p>
<pre><code class="language-plaintext">HTTP/2 200
date: Fri, 30 Jan 2026 13:04:11 GMT
content-type: text/html
...

&lt;!doctype html&gt;&lt;html lang="en"&gt;...&lt;/html&gt;
</code></pre>
<p>Let’s break down the different components of a response:</p>
<h3>Status Code</h3>
<p>We can find a status code in the very first line, which in this example is <code>200</code>. Status codes tell you whether your request succeeded or failed and why. Classes of Status codes are as follows:</p>
<table>
<thead>
<tr>
<th><strong>Code</strong></th>
<th><strong>Meaning</strong></th>
</tr>
</thead>
<tbody><tr>
<td><code>100</code>-<code>199</code></td>
<td>Informational responses</td>
</tr>
<tr>
<td><code>200</code>-<code>299</code></td>
<td>Successful responses</td>
</tr>
<tr>
<td><code>300</code>-<code>399</code></td>
<td>Redirection messages</td>
</tr>
<tr>
<td><code>400</code>-<code>499</code></td>
<td>Client error responses</td>
</tr>
<tr>
<td><code>500</code>-<code>599</code></td>
<td>Server error responses</td>
</tr>
</tbody></table>
<h3>Response Headers</h3>
<p>Everything between the status line and the blank line is made up of headers:</p>
<pre><code class="language-plaintext">date: Fri, 30 Jan 2026 13:13:51 GMT
content-type: text/html
cf-ray: 9c613aa01ac03b49-BOM
last-modified: Fri, 30 Jan 2026 05:47:18 GMT
...
</code></pre>
<p>Headers are metadata about the response. They tell you what type of data is in the body, when did the server generate the response, whatt server software handled the request, etc.</p>
<h3>Response Body</h3>
<p>After a blank line, the actual data begins:</p>
<pre><code class="language-plaintext">&lt;!doctype html&gt;&lt;html lang="en"&gt;...&lt;/html&gt;
</code></pre>
<p>This part is the real content you asked for. For websites, it’s HTML. For APIs, it’s JSON.</p>
<hr />
<h2>Conclusion</h2>
<p>A server response is more than just what you see. The status code, headers, and body each give you important information. By learning to read all three parts, you gain full visibility into how your requests are handled. This makes cURL an incredibly powerful tool for testing and troubleshooting any web API.</p>
]]></content:encoded></item><item><title><![CDATA[DNS Records Made Simple: A, AAAA, NS, CNAME, MX, TXT]]></title><description><![CDATA[Introduction
DNS is a magical system powering the web invisibly. When you enter youtube.com in your browser, your browser does not know where to get the data to load up the YouTube website and render ]]></description><link>https://blog.sameerbhagtani.dev/dns-records-made-simple</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/dns-records-made-simple</guid><category><![CDATA[dns]]></category><category><![CDATA[internet]]></category><category><![CDATA[networking]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Fri, 30 Jan 2026 11:04:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769877459733/b2b62a06-0cd8-4d8c-9fdf-cec80ab374b9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>DNS is a magical system powering the web invisibly. When you enter <code>youtube.com</code> in your browser, your browser does not know where to get the data to load up the YouTube website and render it to show you. This is where DNS comes in. It’s a system of multiple different servers around the world that help you find out the IP address associated with a particular domain name.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769264198037/57cdd49b-9af2-4396-b340-0a86b0512168.png" alt="Browser querying DNS server and then YouTube server using IP address" style="display:block;margin:0 auto" />

<p>However, DNS isn’t just about getting the IP address to load up a website. DNS is much more than that. DNS has this thing called “records”. An IP address is simply one of those records. In this blog post, we are going to take a deep dive into what these DNS records are, why we even need them, and what the different types of records and their use cases are.</p>
<hr />
<h2>Pre-Requisites</h2>
<p>I assume if you’re reading this blog post, you already know what domains are, why we need them, what DNS is, and how the DNS hierarchy works. If you do not, you can read my previous blog post that covers these exact concepts:</p>
<p><a href="https://blog.sameerbhagtani.dev/dns-resolution-explained">DNS Resolution Explained: How Websites Reach Your Browser</a></p>
<hr />
<h2>What are DNS Records?</h2>
<p>DNS records, also referred to as entries in DNS zone files, are instructions that live in authoritative DNS servers. These provide different types of information about the domain name, such as:</p>
<ul>
<li><p>What IP address is associated with this domain?</p>
</li>
<li><p>Which DNS servers are authoritative for this domain?</p>
</li>
<li><p>Which mail server(s) receive emails for this domain?</p>
</li>
</ul>
<hr />
<h2>Why Do We Need DNS Records?</h2>
<p>DNS is just a system. It is nothing without DNS records. DNS records hold the actual information about a domain. Imagine listing a product on Amazon, but providing no details about it. This is exactly what DNS would be like without DNS records. Without DNS records, the DNS system would know that a particular domain exists, but wouldn’t know what to do with it.</p>
<p>DNS records are needed because</p>
<ul>
<li><p>they tell browsers where to go</p>
</li>
<li><p>they tell email systems where to deliver mail</p>
</li>
<li><p>they allow aliases and flexibility</p>
</li>
<li><p>they prove ownership and improve security</p>
</li>
</ul>
<hr />
<h2>DNS Records</h2>
<h3>A Record</h3>
<div>
<div>💡</div>
<div>The question it answers: Where should the browser go?</div>
</div>

<p>This is the most fundamental DNS record. The A stands for “Address”, specifically an IPv4 address. An A record maps a domain name to an IPv4 address (e.g.: <code>142.250.70.78</code>). This IPv4 address is the address of the server that is hosting the website associated with this domain name. This helps browsers know where to connect and fetch the website data from. Here’s an example:</p>
<table>
<thead>
<tr>
<th><strong>Type</strong></th>
<th><strong>Name</strong></th>
<th><strong>Content</strong></th>
</tr>
</thead>
<tbody><tr>
<td>A</td>
<td>example.com</td>
<td>142.250.70.78</td>
</tr>
</tbody></table>
<h3>AAAA Record</h3>
<div>
<div>💡</div>
<div>The question it answers: Where should the browser go?</div>
</div>

<p>This record is very similar to the <code>A</code> record. It answers the exact same question. The difference is that an <code>A</code> record maps to an IPv4 address, whereas an <code>AAAA</code> record maps to an IPv6 address that looks something like <code>2001:0db8:85a3:0000:0000:8a2e:0370:7334</code>. Here’s an example:</p>
<table>
<thead>
<tr>
<th><strong>Type</strong></th>
<th><strong>Name</strong></th>
<th><strong>Content</strong></th>
</tr>
</thead>
<tbody><tr>
<td>AAAA</td>
<td>example.com</td>
<td>2001:0db8:85a3:0000:0000:8a2e:0370:7334</td>
</tr>
</tbody></table>
<h3>NS Record</h3>
<div>
<div>💡</div>
<div>The question it answers: Who is in charge of this domain?</div>
</div>

<p>Remember the authoritative server in the DNS hierarchy? The <code>NS</code> record points to that. It tells the internet which name servers are authoritative for this domain. In other words, which name servers hold all the DNS records for this domain. Here’s an example:</p>
<table>
<thead>
<tr>
<th><strong>Type</strong></th>
<th><strong>Name</strong></th>
<th><strong>Value</strong></th>
</tr>
</thead>
<tbody><tr>
<td>NS</td>
<td>@</td>
<td>ns1.example-dns.com</td>
</tr>
</tbody></table>
<h3>CNAME Record</h3>
<div>
<div>💡</div>
<div>The question it answers: Which domain is this domain an alias of?</div>
</div>

<p>A CNAME record, which stands for Canonical Name, is quite simple. It helps us create an alias, like a nickname, to another domain. For example, you may create an alias where <code>www.example.com</code> points to <code>example.com</code>. So whenever someone tries to visit <code>www.example.com</code>, it will resolve to <code>example.com</code>.</p>
<p>Another use case is when we host a website on a managed hosting service like Vercel, Render, Netlify, etc. and get back a randomized domain name. We can take that domain and create a CNAME record in our DNS settings like this:</p>
<table>
<thead>
<tr>
<th><strong>Type</strong></th>
<th><strong>Name</strong></th>
<th><strong>Content</strong></th>
</tr>
</thead>
<tbody><tr>
<td>CNAME</td>
<td>example</td>
<td>776a4c73a53a8988.vercel-dns-017.com</td>
</tr>
</tbody></table>
<h3>MX Record</h3>
<div>
<div>💡</div>
<div>The question it answers: Which mail server(s) receive emails for this domain?</div>
</div>

<p>I am sure you have seen those fancy emails that look like <code>contact@example.com</code>. We can create our own email addresses to receive emails based on our domain. And in order to do that, we use the <code>MX</code> record. It tells email systems where to deliver emails sent to <code>contact@example.com</code>. Here’s an example:</p>
<table>
<thead>
<tr>
<th><strong>Type</strong></th>
<th><strong>Name</strong></th>
<th><strong>Mail server</strong></th>
</tr>
</thead>
<tbody><tr>
<td>MX</td>
<td>@</td>
<td>mail.example.com</td>
</tr>
</tbody></table>
<h3>TXT Record</h3>
<div>
<div>💡</div>
<div>The question it answers: What text-based information is associated with this domain?</div>
</div>

<p>The <code>TXT</code> record is used for things like:</p>
<ul>
<li><p>Domain ownership and verification</p>
</li>
<li><p>Email security (SPF, DKIM, DMARC)</p>
</li>
<li><p>Service configuration</p>
</li>
</ul>
<p>For example, when you deploy your website on a managed hosting service like Vercel, you usually connect your own domain to it using a <code>CNAME</code> record. But here’s the important part: anyone can create a <code>CNAME</code> record that points to a Vercel hostname, because that only requires knowing the target domain name.</p>
<p>So if that were the only step, someone could try to take your domain name and point it to their own Vercel project. To prevent this, Vercel needs proof that you actually control the domain you are trying to connect.</p>
<p>This is where <code>TXT</code> records come in. Vercel gives you a unique secret verification value and asks you to add it as a <code>TXT</code> record in your domain’s DNS settings, like this:</p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Name</th>
<th>Content</th>
</tr>
</thead>
<tbody><tr>
<td>TXT</td>
<td>_vercel</td>
<td>vc-domain-verify=example.com,abc123xyz</td>
</tr>
</tbody></table>
<p>Only the person who has access to the DNS settings of example.com can add this <code>TXT</code> record. Vercel then performs a DNS lookup for this <code>TXT</code> record. If it finds the exact secret value it generated, it knows that the person connecting the domain really controls it.</p>
<hr />
<h2>Putting it All Together</h2>
<p>A single website usually uses multiple DNS records at the same time, each solving a different problem. When you visit a website, this is what typically happens:</p>
<ol>
<li><p>DNS asks the authoritative servers (defined by <code>NS</code> records) for information about the domain.</p>
</li>
<li><p>It follows any <code>CNAME</code> aliases if they exist.</p>
</li>
<li><p>It finally gets an <code>A</code> or <code>AAAA</code> record containing the server’s IP address.</p>
</li>
<li><p>The browser connects to that IP and loads the website.</p>
</li>
<li><p>Meanwhile, <code>MX</code> and <code>TXT</code> records quietly handle email and verification/security tasks in the background.</p>
</li>
</ol>
<hr />
<h2>Conclusion</h2>
<p>DNS records are the building blocks that tell the internet what to do with your domain. Some point your browser to the right server, some handle email, and others prove ownership and add security. Together, they turn a simple domain name into a fully working website and communication system.</p>
]]></content:encoded></item><item><title><![CDATA[Emmet for HTML: Write HTML at Lightning Speed]]></title><description><![CDATA[Introduction
Writing raw HTML can feel painfully slow. You type <div>, close it, add classes, nest elements, and repeat the same patterns again and again. It works, but it’s repetitive and time-consum]]></description><link>https://blog.sameerbhagtani.dev/emmet-for-html</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/emmet-for-html</guid><category><![CDATA[Web Development]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[HTML]]></category><category><![CDATA[CSS]]></category><category><![CDATA[CSS3]]></category><category><![CDATA[Emmet]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Tue, 27 Jan 2026 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769885492128/6f4bca01-90ec-4036-aa04-fc210e49cc27.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Writing raw HTML can feel painfully slow. You type <code>&lt;div&gt;</code>, close it, add classes, nest elements, and repeat the same patterns again and again. It works, but it’s repetitive and time-consuming.</p>
<p>What if you could write one short line, and instantly get five properly nested list items?</p>
<pre><code class="language-xml">ul&gt;li*5
</code></pre>
<p>That’s exactly what Emmet does. It turns tiny shortcuts into full HTML structures, saving you tons of typing and effort.</p>
<hr />
<h2>What Emmet Is</h2>
<p>Emmet is a shortcut language for HTML. You write a short abbreviation, press a key (usually <code>Tab</code>), and your code editor expands it into complete HTML. Think of it like autocomplete but with superpowers:</p>
<ul>
<li><p>You type less</p>
</li>
<li><p>You get more code</p>
</li>
<li><p>And it’s perfectly formatted</p>
</li>
</ul>
<hr />
<h2>How Emmet Works Inside Code Editors</h2>
<p>Most modern code editors like VS Code have Emmet built in. The flow is simple:</p>
<ol>
<li><p>Type an Emmet abbreviation.</p>
</li>
<li><p>Press <code>Tab</code> (or <code>Enter</code>, depending on settings).</p>
</li>
<li><p>The editor replaces the abbreviation with full HTML.</p>
</li>
</ol>
<p>You never leave your keyboard, and you don’t manually write opening/closing tags again and again.</p>
<hr />
<h2>Creating Elements</h2>
<h3>Single Element</h3>
<p>Here is the simplest example:</p>
<ul>
<li>Emmet Abbreviation:</li>
</ul>
<pre><code class="language-xml">div
</code></pre>
<ul>
<li>Expanded HTML:</li>
</ul>
<pre><code class="language-xml">
&lt;div&gt;&lt;/div&gt;
</code></pre>
<p>You just write the tag name. Emmet writes the full element.</p>
<h3>Multiple Elements</h3>
<p>Another example of creating multiple elements quickly is below:</p>
<ul>
<li>Emmet Abbreviation:</li>
</ul>
<pre><code class="language-xml">h1+p
</code></pre>
<ul>
<li>Expanded HTML:</li>
</ul>
<pre><code class="language-xml">&lt;h1&gt;&lt;/h1&gt;
&lt;p&gt;&lt;/p&gt;
</code></pre>
<p>The <code>+</code> means “next sibling element”.</p>
<hr />
<h2>Adding Classes, IDs, and Attributes</h2>
<ul>
<li>You can add Classes, IDs, and attributes by using a CSS selector-like syntax.</li>
</ul>
<h3>Classes</h3>
<ul>
<li>Emmet Abbreviation:</li>
</ul>
<pre><code class="language-xml">div.container
</code></pre>
<ul>
<li>Expanded HTML:</li>
</ul>
<pre><code class="language-xml">&lt;div class="container"&gt;&lt;/div&gt;
</code></pre>
<h3>IDs</h3>
<ul>
<li>Emmet Abbreviation:</li>
</ul>
<pre><code class="language-xml">section#hero
</code></pre>
<ul>
<li>Expanded HTML:</li>
</ul>
<pre><code class="language-xml">&lt;section id="hero"&gt;&lt;/section&gt;
</code></pre>
<h3>Attributes</h3>
<ul>
<li>Emmet Abbreviation:</li>
</ul>
<pre><code class="language-xml">input[type="text"]
</code></pre>
<ul>
<li>Expanded HTML:</li>
</ul>
<pre><code class="language-xml">&lt;input type="text"&gt;
</code></pre>
<h3>Combined Example</h3>
<ul>
<li>Emmet Abbreviation:</li>
</ul>
<pre><code class="language-xml">button.btn.primary[type="submit"]
</code></pre>
<ul>
<li>Expanded HTML:</li>
</ul>
<pre><code class="language-xml">&lt;button class="btn primary" type="submit"&gt;&lt;/button&gt;
</code></pre>
<hr />
<h2>Creating Nested Elements</h2>
<p>You can use <code>&gt;</code> to put one element inside another.</p>
<ul>
<li>Emmet Abbreviation:</li>
</ul>
<pre><code class="language-xml">ul&gt;li
</code></pre>
<ul>
<li>Expanded HTML:</li>
</ul>
<pre><code class="language-xml">&lt;ul&gt;
    &lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
</code></pre>
<h3>Deeper Nesting</h3>
<ul>
<li>Emmet Abbreviation:</li>
</ul>
<pre><code class="language-xml">div&gt;ul&gt;li
</code></pre>
<ul>
<li>Expanded HTML:</li>
</ul>
<pre><code class="language-xml">&lt;div&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
</code></pre>
<p>Each <code>&gt;</code> means “go one level deeper”.</p>
<hr />
<h2>Repeating Elements Using Multiplication</h2>
<p>You can use <code>*</code> to repeat elements.</p>
<ul>
<li>Emmet Abbreviation:</li>
</ul>
<pre><code class="language-xml">ul&gt;li*3
</code></pre>
<ul>
<li>Expanded HTML:</li>
</ul>
<pre><code class="language-xml">&lt;ul&gt;
    &lt;li&gt;&lt;/li&gt;
    &lt;li&gt;&lt;/li&gt;
    &lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
</code></pre>
<hr />
<h2>Generating Full HTML Boilerplate</h2>
<p>You can create a complete HTML boilerplate with one word.</p>
<ul>
<li>Emmet Abbreviation:</li>
</ul>
<pre><code class="language-xml">!
</code></pre>
<ul>
<li>Expanded HTML:</li>
</ul>
<pre><code class="language-xml">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
    &lt;head&gt;
        &lt;meta charset="UTF-8" /&gt;
        &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
        &lt;title&gt;Document&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<hr />
<h2>Conclusion</h2>
<p>Emmet turns slow, repetitive HTML writing into a fast, almost conversational process. By learning a few simple symbols like <code>&gt;</code>, <code>+</code>, <code>.</code>, <code>#</code>, <code>*</code> and <code>!</code>, you can generate complex structures in seconds.</p>
<p>Start small, use it daily, and soon typing full HTML by hand will feel outdated.</p>
]]></content:encoded></item><item><title><![CDATA[DNS Resolution Explained: How Websites Reach Your Browser]]></title><description><![CDATA[Introduction
Imagine you’re sitting down for dinner and you open youtube.com on your phone, laptop, or TV to watch something while enjoying your meal. Now, unless you’ve been living under a rock, you ]]></description><link>https://blog.sameerbhagtani.dev/dns-resolution-explained</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/dns-resolution-explained</guid><category><![CDATA[dns]]></category><category><![CDATA[internet]]></category><category><![CDATA[networking]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Sat, 24 Jan 2026 11:42:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769878253843/01c8f2aa-bdfb-4b65-a76b-a07589bc8427.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Imagine you’re sitting down for dinner and you open <code>youtube.com</code> on your phone, laptop, or TV to watch something while enjoying your meal. Now, unless you’ve been living under a rock, you know you need an active internet connection to open a website like YouTube. That’s because the website is hosted on a remote server (just a fancy name for a computer that serves data over the internet).</p>
<p>But have you ever wondered how your computer, which only understands 0s and 1s, is able to find the exact remote server that hosts <code>youtube.com</code>, among billions of other servers on the internet?</p>
<hr />
<h2>What are Domains?</h2>
<p>We don’t remember phone numbers of our friends and family members anymore. We simply look up their saved contact in our phones. If you think about it, your contacts app simply maintains a mapping of your friend’s name to their phone number. This saves you the hassle of remembering the phone numbers of all your friends, family members, etc.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769261443920/e26d8e96-56f6-47ba-9e40-84a90b9e1986.png" alt="Contacts app mapping names to phone numbers (analogy for DNS)" style="display:block;margin:0 auto" />

<p>Now coming to the point, you might have already heard the term “IP addresses” in cool hacker movies 😎. They look something like this: <code>142.250.70.78</code>. An IP address is like a phone number, a unique identifier for every device on the internet. So your smartphone has a unique IP address, your computer has a unique IP address, and even your smart refrigerator has one! Likewise, the YouTube server also has an IP address. Since these IPs are unique, if we somehow get our hands on the IP address of YouTube’s server, we will be able to contact the server and ask it for all the data we need to load up the YouTube website in our browser.</p>
<p>And this is where the problem arrives. We, as humans, who can’t even remember 10 phone numbers normally, can surely never remember the IP addresses of billions of websites out there! The solution is domains. A domain like <code>youtube.com</code> is simply a user-friendly name that we can remember instead of something like <code>142.250.70.78</code>. This is just like how we save our friend’s phone numbers with their name, so that we don’t have to remember such long numbers.</p>
<hr />
<h2>Anatomy of a Domain</h2>
<p>Here’s how a domain name is structured (subdomain, SLD, and TLD):</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769261484094/fff3baf5-85d0-4969-b612-7c61eae6a9ec.png" alt="Domain anatomy showing subdomain, SLD, and TLD" style="display:block;margin:0 auto" />

<hr />
<h2>What is Name Resolution?</h2>
<p>Now that we know what domains are, we need to understand this fancy term called “Domain Name Resolution.” Just like I explained in the previous section, domains are surely easy to remember, however we need a process that converts these domains to their IP addresses, so that when we enter a website’s domain, the browser can find its IP address and load the website up for us. This process is called Name Resolution, since we are “resolving” the domain name to its IP address.</p>
<hr />
<h2>DNS: The Contacts App of the Internet</h2>
<p>DNS stands for Domain Name System. For now, you can think of it as a server that maintains a mapping of a website’s domain name, for example, <code>youtube.com</code>, to its IP address. This means whenever you type <code>youtube.com</code> in your browser, it simply reaches out to a DNS server, asks for its IP, and then goes and gets all the website data from the server having that IP.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769264238113/e0d7f2cb-c8c8-4c89-9dd8-d18e983716c7.png" alt="Browser querying DNS server and then YouTube server using IP address" style="display:block;margin:0 auto" />

<p>However, this is just a high-level overview. In reality, this process is much larger, involving multiple different steps and many different types of DNS servers.</p>
<hr />
<h2>The DNS Hierarchy</h2>
<p>Now that you have a high-level understanding of what domains are, why we need them, and how DNS resolves a domain to an IP address, let’s deep dive into the series of steps that happen behind the scenes whenever you enter a website’s domain name in your browser.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769261532890/ac6bb6a4-1682-462a-851c-9530b4d68205.png" alt="DNS resolution flow: browser → recursive resolver → root → TLD → authoritative" style="display:block;margin:0 auto" />

<h3>Component 1: Browser</h3>
<p>When you enter a domain name in your browser (for example, <code>youtube.com</code>), the browser first checks its own DNS cache before making a request anywhere. This is because you may have visited that website before, and the browser might have cached its IP address to save time in the future.</p>
<p>If the IP is found in the cache, there’s no need to reach out to any DNS server. The browser can directly connect to the website’s server and fetch the required data.</p>
<h3>Component 2: Stub Resolver</h3>
<p>A stub resolver is a small DNS client built into your operating system. Its job is very simple. It receives the DNS query from your browser and forwards it to a recursive DNS resolver.</p>
<h3>Component 3: Recursive DNS Resolver</h3>
<p>This is the most important component in the DNS hierarchy. A recursive DNS resolver is a type of DNS server whose job is to find the IP address of a domain by contacting other DNS servers step-by-step until it gets the final answer.</p>
<p>As you can see in the diagram, it acts like a middleman between your browser and the rest of the DNS system. However, before making any further requests, the recursive resolver also checks its own cache. If it already has the IP address stored (and the TTL hasn’t expired), it saves time and simply returns the cached answer.</p>
<h3>Component 4: Root Server</h3>
<p>Root servers are the topmost DNS servers in the hierarchy. They do not know the IP addresses of websites like <code>youtube.com</code>. However, they do know where to find the next step.</p>
<p>When the recursive resolver asks a root server about <code>youtube.com</code>, the root server looks at the <strong>Top-Level Domain (TLD)</strong> part (<code>.com</code>) and responds with a referral to the TLD name servers responsible for <code>.com</code>.</p>
<p>In simple words, the root server responds with something like:</p>
<blockquote>
<p>“I don’t know the IP for <code>youtube.com</code>, but here are the DNS servers that manage <code>.com</code>.”</p>
</blockquote>
<div>
<div>💡</div>
<div>Bonus: There are only <strong>13 named root servers</strong> (labeled <code>A</code> through <code>M</code>). However, they are represented by 1,750+ individual server instances distributed globally using something called <strong>Anycast routing</strong>.</div>
</div>

<h3>Component 5: TLD Server</h3>
<p>After getting referred to the <code>.com</code> TLD servers, the recursive DNS resolver contacts one of them. The TLD server checks the <strong>Second-Level Domain (SLD)</strong> in the query (like <code>youtube</code> in <code>youtube.com</code>) and responds with the authoritative name servers for that domain.</p>
<p>So the TLD server basically says:</p>
<blockquote>
<p>“I don’t know the final IP either, but here are the authoritative servers for <code>youtube.com</code>.“</p>
</blockquote>
<h3>Component 6: Authoritative Server</h3>
<p>Authoritative DNS servers are the final source of truth for a domain. These servers are usually managed by your DNS provider/host like Cloudflare, GoDaddy, Hostinger, etc.</p>
<p>They store different DNS records for your domain, such as:</p>
<ul>
<li><p><code>A/AAAA</code> (IP address)</p>
</li>
<li><p><code>CNAME</code></p>
</li>
<li><p><code>MX</code>, etc.</p>
</li>
</ul>
<p>The recursive resolver reaches out to the authoritative server and asks for the <code>A</code> (or <code>AAAA</code>) record of the domain. This record contains the IP address of the server hosting the website.</p>
<p>Finally, this IP address is returned to your browser, and your browser can then connect to the website’s server and fetch the actual website data.</p>
<h3>Summary</h3>
<p>The entire process can be summarized as the <strong>quest for finding the A record</strong> of the domain name you entered. That A record can either be in your browser cache, or in the DNS resolver’s cache, or the resolver may have to do the entire process step-by-step, querying each server and finding the next location every time, in order to find it.</p>
<img src="https://media1.tenor.com/m/fAuO9yYP9PIAAAAC/bob-odenkirk-saul-goodman.gif" alt="" style="display:block;margin:0 auto" />

<p>Also, do note that this entire process only finds us the IP address of YouTube’s server. This does not fetch the data of YouTube’s website itself. That is done after the browser receives the IP address from this process.</p>
<hr />
<h2><code>dig</code>: A DNS Diagnostic Tool</h2>
<p>Before finishing, let’s take a quick look at <code>dig</code>. <code>dig</code> is a very useful command-line utility, that you can use to query DNS servers. By using <code>dig</code>, you can find out things like:</p>
<ul>
<li><p>What IP address is associated with this domain?</p>
</li>
<li><p>Which DNS servers are authoritative for this domain?</p>
</li>
<li><p>Which mail server(s) receive emails for this domain?</p>
</li>
</ul>
<h3>Querying for an IP Address</h3>
<p>In order to fetch the IP address of a domain, you can simply run the following command:</p>
<pre><code class="language-bash">dig youtube.com
</code></pre>
<p>In the output, you will see a section like this:</p>
<pre><code class="language-plaintext">;; ANSWER SECTION:
youtube.com.		153	IN	A	142.250.70.78
</code></pre>
<p>This is YouTube’s IP address.</p>
<div>
<div>💡</div>
<div>Note: By default, <code>dig</code> asks for the A record, which holds the IP address.</div>
</div>

<h3>Querying a Specific DNS Record</h3>
<p>We can also query for a particular record by doing:</p>
<pre><code class="language-bash">dig youtube.com NS
</code></pre>
<p>The output would look something like this:</p>
<pre><code class="language-plaintext">;; ANSWER SECTION:
youtube.com.		238608	IN	NS	ns4.google.com.
youtube.com.		238608	IN	NS	ns2.google.com.
youtube.com.		238608	IN	NS	ns3.google.com.
youtube.com.		238608	IN	NS	ns1.google.com.
</code></pre>
<h3>Querying a Specific DNS Server</h3>
<p>We can also query a particular DNS server. For example, now that we know the nameservers of <code>youtube.com</code>, let’s query a specific one to get the A record:</p>
<pre><code class="language-bash">dig @ns4.google.com youtube.com A
</code></pre>
<p>The output would look like this:</p>
<pre><code class="language-plaintext">;; ANSWER SECTION:
youtube.com.		300	IN	A	142.250.207.206
</code></pre>
<div>
<div>💡</div>
<div>Note: The IP address might be different than what we saw in the previous section, since big sites like <code>youtube.com</code> run on multiple different servers, load balancers, etc.</div>
</div>

<h3>Fetching the Root Servers</h3>
<p>We can fetch all 13 root DNS servers by doing this:</p>
<pre><code class="language-bash">dig . NS
</code></pre>
<p>The output would look like this:</p>
<pre><code class="language-plaintext">;; ANSWER SECTION:
.			205024	IN	NS	a.root-servers.net.
.			205024	IN	NS	b.root-servers.net.
.			205024	IN	NS	c.root-servers.net.
.			205024	IN	NS	d.root-servers.net.
.			205024	IN	NS	e.root-servers.net.
.			205024	IN	NS	f.root-servers.net.
.			205024	IN	NS	g.root-servers.net.
.			205024	IN	NS	h.root-servers.net.
.			205024	IN	NS	i.root-servers.net.
.			205024	IN	NS	j.root-servers.net.
.			205024	IN	NS	k.root-servers.net.
.			205024	IN	NS	l.root-servers.net.
.			205024	IN	NS	m.root-servers.net.
</code></pre>
<hr />
<h2>Conclusion</h2>
<p>DNS is indeed a magical system powering the web invisibly. It is not a single server, but an entire system of servers that help your browser get the associated IP address for a domain. These IP addresses are sharded around the world, distributed across multiple servers based on the TLD, authoritative servers, etc. And the DNS resolver does the job of recursively finding out the next location in the DNS hierarchy until we find the <code>A</code> record.</p>
]]></content:encoded></item><item><title><![CDATA[Demystifying Git: Internals Explained]]></title><description><![CDATA[Introduction
Git was created by Linus Torvalds (the creator of the Linux kernel) in April 2005, as a system for managing the Linux codebase over time. He created the initial version of Git in a very s]]></description><link>https://blog.sameerbhagtani.dev/demystifying-git-internals</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/demystifying-git-internals</guid><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Fri, 16 Jan 2026 22:38:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768645993770/841d466e-75f0-4f01-9aef-be09ef4b2346.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p><a href="https://git-scm.com/">Git</a> was created by <a href="https://en.wikipedia.org/wiki/Linus_Torvalds">Linus Torvalds</a> (the creator of the <a href="https://en.wikipedia.org/wiki/Linux">Linux</a> kernel) in April 2005, as a system for managing the Linux codebase over time. He created the initial version of Git in a very short time span of <strong>10 days</strong>! Fast forward to 2025, over 90% of developers use this amazing software in every project, multiple businesses have been built around it, such as GitHub, GitLab, etc., and it has truly revolutionized writing software forever. Imagine creating the foundation of an entire system that will change coding forever, only in a span of 10 days!</p>
<p>However, many of us developers still do not understand how Git actually works internally. The understanding about the internals of Git is surely not going to help you in your day-to-day git activities, but it will make you a better engineer overall, helping you to understand the thought process behind such a robust system.</p>
<hr />
<h2>Pre-Requisites</h2>
<p>I assume if you’re reading this blog post, you already know about what Git is, what problem does it solve, the basic git workflow and some basic commands too. If you do not, you can read my previous blog posts that cover these exact concepts:</p>
<ol>
<li><p><a href="https://blog.sameerbhagtani.dev/why-version-control-exists">Why Version Control Exists: A Video Game Perspective</a></p>
</li>
<li><p><a href="https://blog.sameerbhagtani.dev/learning-git-commands">Learning Git Commands Through Video Game Mechanics</a></p>
</li>
</ol>
<p>Once you know these concepts, you will be ready to deep-dive into the mysteries of Git!</p>
<hr />
<h2>Porcelain vs Plumbing Commands</h2>
<p>All the Git commands are divided into 2 categories:</p>
<ol>
<li><p>Porcelain Commands: These are high-level, friendly commands that we actually use in our day-to-day Git usage. You might already be familiar with some of these commands like <code>init</code>, <code>add</code>, <code>commit</code>, <code>status</code>, etc.</p>
</li>
<li><p>Plumbing Commands: These are low-level internal commands that are not meant for daily use. They can be used to inspect/manipulate Git internals. Some of these commands are <code>hash-object</code>, <code>cat-file</code>, <code>write-tree</code>, etc.</p>
</li>
</ol>
<p>It is also important to understand that the Porcelain commands that we use in our day-to-day Git usage, are simply a <strong>high-level abstraction</strong> on top of one or more Plumbing Commands. In other words, they are built on top of one or more Plumbing commands only.</p>
<hr />
<h2>The <code>.git</code> Directory: Git’s Brain</h2>
<p>The first command you run in order to start using Git in any project is:</p>
<pre><code class="language-bash">git init
</code></pre>
<p>This simple porcelain command essentially converts your normal folder holding together a bunch of random code files, into a proper git source code repository. But how does git do it?</p>
<p>When you run this command, Git adds a hidden directory called <code>.git</code> at the root of your project directory. You can confirm this using the following command on unix terminals:</p>
<pre><code class="language-bash">ls -a
</code></pre>
<p>This command will basically list out all the files and folders in that directory, including hidden ones (because of the <code>-a</code> flag). The output would look something like this:</p>
<pre><code class="language-plaintext">.  ..  main.c  .git
</code></pre>
<p>And that is literally it! A single directory is all that’s needed to manage all the files of your projects, every commit you make, every branch you make, every merge you do, literally everything! Let’s see how.</p>
<hr />
<h2>Anatomy of the <code>.git</code> Directory</h2>
<p>The <code>.git</code> directory consists of several files and sub-directories that have specific purposes in Git’s overall design. A high-level overview of the directory would look something like this:</p>
<pre><code class="language-plaintext">.git/
├── objects/
├── refs/
│   └── heads/
│       ├── main
│       ├── feature1_branch
│       └── feature2_branch
├── HEAD
├── index
└── config
</code></pre>
<p>There are a bunch of other files and directories too, but we will focus upon these for now.</p>
<hr />
<h2>How Git Stores Data?</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768597172009/47f3ab0d-efbe-41c8-b944-4fe36ab5382b.png" alt="Git stores content using hashes as keys; same content produces the same hash." style="display:block;margin:0 auto" />

<p>Git is a <strong>content-addressable file system</strong>. This means that Git stores data by using the content itself as the “address” (ID). That address/ID is more properly referred to as a “hash” in Git terminology.</p>
<p>So for example, if you have the following content in any of your files:</p>
<pre><code class="language-plaintext">Hello World
</code></pre>
<p>Then Git will generate a hash for this content that would look something like this:</p>
<pre><code class="language-plaintext">0a4d55a8d778e5022fab701977c5d840bbc486d0
</code></pre>
<p>Technically, Git hashes the content along with a small header (object type + size).</p>
<div>
<div>💡</div>
<div>Git uses the SHA-1 algorithm to generate these hashes. The output is a 160-bit string encoded in hexadecimal, and since 1 hex digit = 4 bits, 160/4 = 40 characters. In short, each such hash ID is a 40 character long hexadecimal string.</div>
</div>

<hr />
<h2>Objects: Git’s Driving Force</h2>
<p>Now that we understand that Git stores data using hashes, we need to understand: What exactly is Git storing behind those hashes? The answer is: <strong>Git stores everything as objects</strong>. Every commit you make, every file, and every folder structure is represented using Git objects, which are stored in the <code>.git/objects</code> directory.</p>
<p>Git primarily works with <strong>three main types</strong> of objects:</p>
<h3>Blob (Binary Large Object)</h3>
<p>Blob objects store the actual contents of your file. They do not store any metadata, no filename, no path, no permissions, nothing other than the contents of your file.</p>
<p>Do note that the contents of your files are not simply copied over to the <code>.git/objects</code> directory as blob objects. Instead, Git creates a blob object for the content and stores it in a <strong>compressed format</strong> (using <strong>zlib</strong>) to save space.</p>
<p>The following plumbing commands can be used on blob objects:</p>
<pre><code class="language-bash">git cat-file -p blob_hash   # shows original content
git cat-file -s blob_hash   # shows uncompressed size
</code></pre>
<h3>Tree</h3>
<p>Tree objects store the actual directory structure. They store a mapping that looks like this:</p>
<pre><code class="language-plaintext">100644 blob a1b2c3  main.cpp
040000 tree d4e5f6  src
</code></pre>
<p>The above output uses the format :</p>
<pre><code class="language-plaintext">mode object_type hash filename
</code></pre>
<p>Basically, trees map blobs to their filenames. Trees also map sub-trees (i.e. sub-directories) to their corresponding tree objects.</p>
<p>The following plumbing command can be used to view a tree object tied to a particular commit:</p>
<pre><code class="language-bash">git ls-tree commit_hash
</code></pre>
<p>In simpler words, a tree represents a directory and can point to:</p>
<ul>
<li><p>blobs (raw file content)</p>
</li>
<li><p>other trees (sub-directories)</p>
</li>
</ul>
<div>
<div>💡</div>
<div>Why are the filenames stored in the tree object and not the blob itself? If multiple files have the same content, the tree can simply create multiple entries that point to the same blob. This makes Git <strong>space-efficient</strong>.</div>
</div>

<h3>Commit</h3>
<p>A commit object stores the snapshot, the history, and all the metadata. The following plumbing command can be used to view a commit object:</p>
<pre><code class="language-bash">git cat-file -p commit_hash
</code></pre>
<p>The output would look something like this:</p>
<pre><code class="language-plaintext">tree root_tree_hash
parent parent_commit_hash (0 or more)
author name email timestamp
committer name email timestamp

commit message
</code></pre>
<div>
<div>💡</div>
<div>The entire commit timeline forms a graph, not a simple list. This is because a commit can have multiple parents (merge), and also multiple commits can share the same parent (branching). More accurately, a commit timeline is a <strong>DAG</strong> (Directed Acyclic Graph).</div>
</div>

<h3>Relation Between all the Objects</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768599834483/12c6604b-4dfd-4713-ac21-d740ff39a8ce.png" alt="Git commit points to a tree, and the tree points to blobs and subtrees." style="display:block;margin:0 auto" />

<ul>
<li><p>Commits define history.</p>
</li>
<li><p>Trees define structure.</p>
</li>
<li><p>Blobs define content.</p>
</li>
</ul>
<p>A commit points to exactly one tree. That tree represents the entire directory structure of the repository and also further points to blobs which hold the actual data.</p>
<hr />
<h2>Other Parts of the <code>.git</code> Directory</h2>
<p>Let’s quickly go over the other files and directories of the <code>.git</code> directory:</p>
<h3><code>refs</code></h3>
<p><code>refs</code> is a directory with the following structure:</p>
<pre><code class="language-plaintext">refs/
└── heads/
    ├── main
    ├── feature1_branch
    └── feature2_branch
</code></pre>
<p>These files represent different branches and store the hash that points to the latest commit in the respective branches.</p>
<h3><code>HEAD</code></h3>
<p>This is a file that simply stores the name of the current branch. If your current branch is <code>main</code>, the <code>HEAD</code> file’s content would be this:</p>
<pre><code class="language-plaintext">ref: refs/heads/main
</code></pre>
<h3><code>index</code></h3>
<p>This is a file that represents the Git staging area. It stores information about the files you’ve added using <code>git add</code>, so Git knows what exactly to include in the next commit.</p>
<h3><code>config</code></h3>
<p>This is a file that stores repository-specific settings, like the remote URL (<code>origin</code>), default branch, and other local configurations.</p>
<hr />
<h2>Internal Flow of <code>git add</code> and <code>git commit</code></h2>
<h3>Staging</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768646925035/2beae324-ecbb-4ead-a7d8-3d791256aacc.png" alt="Git add flow: working directory → blob object → staging area (index)." style="display:block;margin:0 auto" />

<ol>
<li><p>Let’s say you edit a file called <code>file.txt</code> in your working directory and run the <code>git add file.txt</code> command.</p>
</li>
<li><p>Git reads the content of the file, compresses it, and stores it as a <strong>blob object</strong> inside the <code>.git/objects</code> directory. Do note that if the same content already exists, Git just reuses the existing blob hash, without creating a new one.</p>
</li>
<li><p>Git updates the index i.e., the staging area. It simply adds a record in the <code>.git/index</code> file, which basically states “For <code>file.txt</code>, the staged version is this blob hash”.</p>
</li>
</ol>
<h3>Committing</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768647060150/b1d3f428-4a11-4606-be23-761d01cf2aad.png" alt="Git commit flow: staging area → tree object → commit object → branch pointer updated." style="display:block;margin:0 auto" />

<ol>
<li><p>After the staging phase is over, and you run the <code>git commit</code> command, Git first reads the staging area (index) with the aim of turning it into a permanent snapshot in Git history.</p>
</li>
<li><p>Git converts the staging area into a directory structure and creates a <strong>tree object</strong>.</p>
</li>
<li><p>Git creates a <strong>commit object</strong> that stores:</p>
<ul>
<li><p>the tree hash (snapshot)</p>
</li>
<li><p>the parent commit hash (previous commit)</p>
</li>
<li><p>author info + timestamp</p>
</li>
<li><p>commit message</p>
</li>
</ul>
</li>
<li><p>Git moves the branch pointer by updating the <code>.git/refs/heads/branch_name</code> file, to make sure that particular branch now points to the new commit hash.</p>
</li>
</ol>
<hr />
<h2>Summary</h2>
<ul>
<li><p>Commit → points to a tree → points to blobs and sub-trees</p>
</li>
<li><p>Refs/branches → point to commits</p>
</li>
<li><p>HEAD → tells which branch you’re on</p>
</li>
</ul>
<hr />
<h2>Conclusion</h2>
<p>Git might look like magic from the outside, but internally it’s built on a very simple idea: <strong>store everything as objects, and reference them using hashes</strong>. Once you understand <code>blobs</code>, <code>trees</code>, <code>commits</code>, and how files like <code>HEAD</code>, <code>refs</code>, and <code>index</code> work together, Git starts to feel a lot less mysterious.</p>
]]></content:encoded></item><item><title><![CDATA[Learning Git Commands Through Video Game Mechanics]]></title><description><![CDATA[Introduction
Have you ever died in a video game and worried about losing all your progress? If you didn’t have a saved state, chances are you’ve smashed your keyboard in frustration 😶.


But if you d]]></description><link>https://blog.sameerbhagtani.dev/learning-git-commands</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/learning-git-commands</guid><category><![CDATA[version control]]></category><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Sun, 11 Jan 2026 21:38:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768214205876/da36db63-71f2-477f-99c8-3c1afa6e699b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Have you ever died in a video game and worried about losing all your progress? If you didn’t have a saved state, chances are you’ve smashed your keyboard in frustration 😶.</p>
<img src="https://media1.tenor.com/m/9Jvv_XT_JroAAAAC/super-mario-bros-dead.gif" alt="" style="display:block;margin:0 auto" />

<p>But if you did have a save point, you know how easy it is to jump right back in from the last checkpoint and keep playing like nothing happened 😎. That’s exactly what Git is for your code, a “save game” system that lets you rewind mistakes, experiment freely, and never fear losing hours of work again.</p>
<p>I’ve explained <strong>Version Control Systems</strong> from the ground up in my previous blog post, why they exist, the problems they solve, and how <strong>Git</strong> and <strong>GitHub</strong> fit into the picture, all using video game analogies to make things easier to understand. If you haven’t read it yet, you can check it out here:</p>
<p><a href="https://blog.sameerbhagtani.dev/why-version-control-exists">Why Version Control Exists: A Video Game Perspective</a></p>
<hr />
<h2>What is Git?</h2>
<p>I’ve already covered this in detail in a previous blog post, so let’s quickly brush over the key points.</p>
<ul>
<li><p>Git is a <strong>local</strong> software you use to keep track of changes in your code.</p>
</li>
<li><p>It also keeps tracks of who made what changes (so you know who to blame 😉).</p>
</li>
<li><p>It also keeps track of <strong>every version of your project</strong>, meaning no more folders named <code>final</code>, <code>final_v2</code>, or <code>final_final</code> 😮‍💨.</p>
</li>
<li><p>Git is a <strong>distributed system</strong>, which means every developer has their own complete copy of the project and its history.</p>
</li>
<li><p>You interact with Git mainly through the <strong>command line</strong> (or GUI tools… but where’s the fun in that?).</p>
</li>
</ul>
<hr />
<h2>What Git is not?</h2>
<ul>
<li><p>Git is <strong>not an online platform</strong>.</p>
</li>
<li><p>Git is <strong>not GitHub</strong>. They are completely different things.</p>
</li>
<li><p>Platforms like GitHub are simply associated with Git and extend its functionality by providing:</p>
<ul>
<li><p>shared remote hosting</p>
</li>
<li><p>an easy way to collaborate with others</p>
</li>
</ul>
</li>
<li><p>Git itself works perfectly fine on its own, without the internet.</p>
</li>
</ul>
<hr />
<h2>Demystifying Git Jargon</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768226834703/5f88d9e5-1fd7-4bfb-aeee-6341ae4274d1.png" alt="“Git Jargon” diagram showing repository, remote, branches, staging area, HEAD, commit, and commit hash." style="display:block;margin:0 auto" />

<h3>Repository</h3>
<p>In layman’s terms, a repository refers to the source code folder that Git is tracking. We have to initialize Git within a folder, which essentially tells Git to start tracking all the files inside that folder and makes that folder a “repository”. Git adds a hidden <code>.git</code> folder inside it, where it stores everything, such as the complete history, metadata, and references to remotes, etc.</p>
<h3>Commit</h3>
<p>In our video game analogy, you can think of a “commit” as a “saved state”. It is simply a snapshot of your code at a given point in time. You can create many commits in a series, which basically build out a timeline of commits, allowing you to jump back to a specific commit whenever you want.</p>
<h3>Commit Hash</h3>
<p>Whenever you create a commit, a unique number is generated and associated with that commit like an ID. That unique ID is called a “Commit Hash”. It is a 40-character hexadecimal string.</p>
<h3><code>HEAD</code></h3>
<p>HEAD is a pointer that refers to the current commit you are working on. It simply represents your current position in the entire timeline of commits.</p>
<h3>Staging Area</h3>
<p>Before you take a snapshot of your new changes, or in Git terminology, before you “commit” your new changes, you first have to add them to a staging area. It is simply a convenience feature that allows you to review and prepare all the files before making a commit.</p>
<h3>Branch</h3>
<p>You know how many games provide multiple different save slots, so that you and your brother can both grind the story at the same time without conflicting with each other’s progress? Git has a feature like that too.</p>
<p>Git allows you to create several “branches”, which are like separate timelines of their own. Want to try out a new feature? Simply create a feature branch. If it works, merge it into the main branch. If not, delete it. Your original code remains intact in the main branch.</p>
<h3>Main/Master</h3>
<p>This is simply the default name of the base branch. Previously, it used to be called <code>master</code>. Now, it is called <code>main</code>.</p>
<h3>Remote</h3>
<p>A remote is a reference to another copy of the repository that is hosted at a remote location (usually GitHub).</p>
<h3>Origin</h3>
<p><code>origin</code> is the default name Git gives to the main remote repository.</p>
<hr />
<h2>Git Workflow</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768166071315/2ec1383b-0966-445f-a47e-5bb72b486701.png" alt="A step-by-step diagram showing the Git lifecycle: git init, Working Directory, git add, Staging Area, and git commit." style="display:block;margin:0 auto" />

<ol>
<li><p><strong>Initialization</strong>: You initialize Git within your source code folder and convert your ordinary folder into a Git repository.</p>
</li>
<li><p><strong>Staging Files</strong>: After adding, modifying, or creating new files, you stage them in the Git staging area.</p>
</li>
<li><p><strong>Commit</strong>: After making sure you have staged everything properly, you commit the staged files, which essentially makes a proper snapshot of your code that you can return to if needed.</p>
</li>
</ol>
<hr />
<h2>Installation</h2>
<p>You can install Git by going to the following website and following the instructions as per your operating system:</p>
<p><a href="https://git-scm.com/install/">https://git-scm.com/install/</a></p>
<p>After the installation, open up your terminal and run the following command to verify the installation:</p>
<pre><code class="language-bash">git --version
</code></pre>
<p>If you do get a version number in the output, you’re in the clear!</p>
<hr />
<h2>Essential Commands</h2>
<h3>Initialize a Git Repository</h3>
<p>This is the first command you need to type to turn a regular source code folder into a “git repository.” Once you type this command, you can then use the other Git commands to manage your codebase.</p>
<pre><code class="language-bash">git init
</code></pre>
<h3>Add Files to the Staging Area</h3>
<p>Use the following command to add new or modified files to the Git staging area:</p>
<pre><code class="language-bash">git add fileName1 fileName2
</code></pre>
<p>If you want to add all the new and modified files, you can simply run:</p>
<pre><code class="language-bash">git add .
</code></pre>
<h3>Commit Files: Save the Game</h3>
<p>Once you have modified and added the files you want to save to the staging area, use the following command to make a proper “commit”, i.e., take a screenshot of the current state of your codebase:</p>
<pre><code class="language-bash">git commit -m "some message here that describes the commit"
</code></pre>
<p>You can both add and commit in a single command using the <code>-a</code> flag. However, do note that this combined way only works for the tracked files, i.e., the files Git already knows about and is tracking. It won’t work for files you have added newly and are untracked yet.</p>
<pre><code class="language-bash">git commit -am "some message here that describes the commit"
</code></pre>
<p>It’s just like saving your game and letting out a sigh of relief 😮‍💨, knowing you can come back to this point if you need to.</p>
<h3>Retrieving Logs</h3>
<p>You can see all the commits you have ever made in a Git repository by simply running the following command. It displays the commit hash, the author who made the commit, the date and time of the commit, along with the message.</p>
<pre><code class="language-bash">git log
</code></pre>
<p>If you want to see a concise output with just the commit hash and the message, you can use the <code>--oneline</code> flag:</p>
<pre><code class="language-bash">git log --oneline
</code></pre>
<p>If you want to see the logs in a graph timeline manner, you can use the <code>--graph</code> flag:</p>
<pre><code class="language-bash">git log --graph
</code></pre>
<h3>Status</h3>
<p>The status command shows you the current status of your Git repository, such as the branch you’re on, untracked (new) files, files added to the staging area, modified files, deleted files, renamed files, etc.</p>
<pre><code class="language-bash">git status
</code></pre>
<p>The <code>-s</code> flag can be used to display a more concise, short-format output:</p>
<pre><code class="language-bash">git status -s
</code></pre>
<p>The output that you’ll receive with the <code>-s</code> flag uses the following status codes:</p>
<pre><code class="language-plaintext">A  : Added
M  : Modified
D  : Deleted
R  : Renamed
?? : Untracked
!! : Ignored
</code></pre>
<h3>Compare Commits</h3>
<p>You can run the following command to compare two commits and check out the differences between them:</p>
<pre><code class="language-bash">git diff commitHash1 commitHash2
</code></pre>
<p>You can also run this command without the hashes to simply compare your working directory with the last staged version (index). However, do note that this only shows the tracked files, i.e., the files Git already knows about and is tracking. It won’t show files you have added newly and are untracked yet.</p>
<pre><code class="language-bash">git diff
</code></pre>
<h3>Reset Your Changes: Load an Old Game State</h3>
<p>Let’s say you messed some code up and want to restart from an old state, just like you would in a video game after dying. Don’t worry, all those commits you made are like checkpoints that you can time travel to with the following commands.</p>
<ul>
<li>Reset a staged file:</li>
</ul>
<pre><code class="language-bash">git reset fileName
</code></pre>
<ul>
<li>Reset all staged files (clear the entire staging area):</li>
</ul>
<pre><code class="language-bash">git reset
</code></pre>
<ul>
<li>Reset a defined number of commits:</li>
</ul>
<pre><code class="language-bash">git reset HEAD~1
</code></pre>
<ul>
<li>Reset up until a particular commit:</li>
</ul>
<pre><code class="language-bash">git reset commitHash
</code></pre>
<ul>
<li>You can also use the <code>--hard</code> flag to reset and also discard all the changes in the working directory:</li>
</ul>
<pre><code class="language-bash">git reset --hard commitHash
</code></pre>
<h3>Reset Changes by Creating a New Commit</h3>
<p>There is another command called <code>revert</code> that resets the commits for you but also preserves the history. The following command will apply the inverse of the commit mentioned.</p>
<pre><code class="language-bash">git revert commitHash
</code></pre>
<div>
<div>💡</div>
<div>Prefer using <code>git revert</code> over <code>git reset</code>, since <code>git reset</code> erases history, while <code>git revert</code> preserves it.</div>
</div>

<hr />
<h2>Conclusion</h2>
<p>Git might look intimidating at first, but at its core, it’s simply a powerful save game system for your code. It gives you the confidence to experiment, break things, and explore new ideas, knowing that you can always jump back to a previous checkpoint if something goes wrong.</p>
<p>My recommendation would be to start using Git for every project you create henceforth. Once you start using commands like add and commit to save your game 😎, and revert to restart once you mess your codebase up 😶, eventually they will become muscle memory to you!</p>
]]></content:encoded></item><item><title><![CDATA[Why Version Control Exists: A Video Game Perspective]]></title><description><![CDATA[Introduction
Imagine you just started playing your favorite video game, GTA, and were greeted with this legendary scene:


You played the game for hours, completing mission after mission. But then, yo]]></description><link>https://blog.sameerbhagtani.dev/why-version-control-exists</link><guid isPermaLink="true">https://blog.sameerbhagtani.dev/why-version-control-exists</guid><dc:creator><![CDATA[Sameer Bhagtani]]></dc:creator><pubDate>Mon, 05 Jan 2026 21:09:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768213980040/a936415d-a8e0-4568-b169-d143590c2167.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2>
<p>Imagine you just started playing <strong>your favorite video game, GTA</strong>, and were greeted with this legendary scene:</p>
<img src="https://media1.tenor.com/m/cJRcMyUAiMcAAAAC/ah-shit-here-we-go-again-ah-shit.gif" alt="" style="display:block;margin:0 auto" />

<p>You played the game for hours, completing mission after mission. But then, you failed a mission badly and wanted to reload from the last mission to try again with a fresh start. And then it hits you, <strong>what if you hadn't saved your game?</strong> 😵 This is exactly the kind of problem Version Control Systems like Git solve for developers.</p>
<hr />
<h2>Problems Faced Before Version Control Systems</h2>
<h3>Lack of a “Load Game” Feature</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767647345636/d9b98323-f181-4432-86ae-f9b37fce671c.png" alt="Flow diagram showing software development with version control, where features are added sequentially and a faulty feature can be easily reverted to a previous stable state." style="display:block;margin:0 auto" />

<p>Imagine you're developing a feature for your <strong>new, shiny todo app</strong> 😎. After several days of work, it didn't meet your expectations. You want to revert to your previous codebase and start over. Without version control systems, you'd have to manually delete various lines and files, which is tedious and error-prone. A VCS like Git gives you a <strong>simple command</strong> that will help you revert to your previous codebase instantly. This is just like being able to load your old game state and play again!</p>
<h3>Lack of a Collaboration System: The Pendrive Problem</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767648113770/930d2b52-7fd1-4b50-a62a-14609069f42e.png" alt="Illustration of collaboration before version control systems, where developers share code using a pendrive, wait for each other to finish, and lack version history, parallel work, and conflict resolution." style="display:block;margin:0 auto" />

<p>You realize you cannot implement this new feature alone and decide to bring in your friend, who just completed his calculator app 😎. You zip the entire codebase and share it <strong>via pendrive or email</strong>. Your friend makes changes and returns it the same way. The problem? There's a high risk of <strong>code conflicts</strong> since you both might modify the same files. Additionally, there's <strong>no system to track changes</strong> from all developers, making it difficult to merge everything back into a single codebase.</p>
<h3>Lack of Accountability</h3>
<p>Let’s say your friend, who is trying to add a new feature to your todo app, accidentally breaks some existing features. He sends the code back to you via a pendrive or email. Meanwhile, you've made your own changes, and now you merge everything together. After merging, <strong>your app doesn’t work anymore!</strong> 😵 And there's no way to tell if it was you or your friend who broke the code! It’s like playing <strong>Call of Duty</strong> with your friends and not knowing who stole your kill 😶.</p>
<h3>Poor Versioning</h3>
<p>Have you ever named your app versions <code>final</code>, <code>final_v2</code>, and even <code>final_final</code>? Without version control systems, it was very hard to keep track of all the versions and the changes those versions had. This forced developers to do the one thing they are notoriously bad at: <strong>naming things</strong> 🫣.</p>
<h2>Solution: Version Control Systems</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767647918576/e410d381-69ef-4bc5-91c4-65d462e86c76.png" alt="Diagram showing collaboration after version control systems, where two developers manage code locally with Git and push and pull changes from a central GitHub repository, enabling version history, parallel work, and conflict resolution." style="display:block;margin:0 auto" />

<p>As the name suggests, a version control system is software whose primary job is to track, manage and control changes to your files, typically your source code, over time. It solves all the problems mentioned above by:</p>
<ul>
<li><p>allowing you to <strong>revert your codebase</strong> to a previous state, like a “load game” feature</p>
</li>
<li><p>making collaboration easy through online platforms like <strong>GitHub</strong></p>
</li>
<li><p>maintaining accountability by recording who made which changes (so you know who to blame 😉)</p>
</li>
<li><p>keeping track of all versions for you, so you don’t have to give your project random names anymore 😮‍💨</p>
</li>
</ul>
<hr />
<h2>Git: Time Machine for Developers</h2>
<p><a href="https://git-scm.com/">Git</a> was created by <a href="https://en.wikipedia.org/wiki/Linus_Torvalds">Linus Torvalds</a> (the creator of the <a href="https://en.wikipedia.org/wiki/Linux">Linux</a> kernel) in April 2005, as a system for managing the Linux codebase overtime. In simpler words, we can think of it as a “Code Tracker”. Git is usually <strong>used through commands</strong> in the terminal (or via GUI tools), but we’ll focus on what it does, not how yet. Git is an example of a <strong>VCS</strong> (Version Control System). There are many other VCSs out there as well, like Mercurial, Apache Subversion (SVN), and Fossil, just to name a few. However, Git is the most popular one.</p>
<p>It is important to understand that Git is purely a <strong>local software</strong>. This means that it is software you run locally on your computer, and it simply keeps tracks of all the changes in your code, who made what changes and when, etc. It is designed to be used by a <strong>single developer</strong> on their <strong>local machine</strong>. This makes Git only a piece of the solution. It does solve many problems, but it is not complete since you would still have to share your Git-managed codebase via a pendrive, email, etc.</p>
<hr />
<h2>GitHub: The Central Source of Truth</h2>
<p><a href="https://github.com/">GitHub</a> is an online platform built on top of Git. It is like a central place where your entire Git-managed codebase is stored. This makes it easier for other developers to simply “pull” (download) the entire codebase from the internet, make changes, and “push” (upload) the modified codebase back. GitHub is what we call a <strong>VCS Remote</strong>. And again, it is not the only one, there are other such online platforms out there like GitLab, BitBucket, GitTea, etc.</p>
<hr />
<h2>Important Note: Git ≠ GitHub</h2>
<p>Many beginners confuse Git and GitHub thinking they are the same. However, based on the above explanations, you might have understood that they are vastly different.</p>
<table>
<thead>
<tr>
<th><strong>Point</strong></th>
<th><strong>Git</strong></th>
<th><strong>GitHub</strong></th>
</tr>
</thead>
<tbody><tr>
<td>What it is</td>
<td>A version control system</td>
<td>A platform/service built around Git</td>
</tr>
<tr>
<td>Purpose</td>
<td>Tracks changes in source code <strong>locally</strong></td>
<td>Hosts Git repositories (Git-managed codebases) <strong>online</strong></td>
</tr>
<tr>
<td>Ownership</td>
<td>Open source</td>
<td>Owned by Microsoft</td>
</tr>
<tr>
<td>Problems that it solves</td>
<td>Version Control, history tracking</td>
<td>Collaboration, Sharing</td>
</tr>
<tr>
<td>Dependency</td>
<td>No Dependency. Works on its own.</td>
<td>Depends on Git to function</td>
</tr>
</tbody></table>
<p><strong>Analogy</strong>: If Git is the <strong>save and load game</strong> feature for your codebase, GitHub is the <strong>central server</strong> that enables you and your friends to play the game together!</p>
<hr />
<h2>Resources to Learn About Git and GitHub</h2>
<ul>
<li><p>The official Git documentation: <a href="https://git-scm.com/docs">https://git-scm.com/docs</a></p>
</li>
<li><p>GitHub Skills: <a href="https://skills.github.com/">https://skills.github.com</a></p>
</li>
</ul>
<hr />
<h2>Conclusion</h2>
<p>Version Control Systems are systems built by developers for developers. Developers realized how difficult it was to manage their codebase, track changes, and work on it collaboratively, so they came up with an efficient solution. One piece is Git, which is the local system keeping track of the entire codebase. The second piece is GitHub, an online platform to host Git repositories, making it easier to work collaboratively.</p>
<p>Learning how to efficiently use Git and GitHub is essential for every developer today. It is not a fancy tool that developers can use to brag about, instead, it is an essential tool born out of necessity.</p>
]]></content:encoded></item></channel></rss>