<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tahsin Abrar</title>
    <description>The latest articles on DEV Community by Tahsin Abrar (@tahsin000).</description>
    <link>https://dev.to/tahsin000</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1084553%2Fd57c59ef-8617-4868-a1e8-7fe07493b0be.png</url>
      <title>DEV Community: Tahsin Abrar</title>
      <link>https://dev.to/tahsin000</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tahsin000"/>
    <language>en</language>
    <item>
      <title>Mid-Year Backend Reset: My H2 Goals for Speed, Security, and Better Docs</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Fri, 03 Jul 2026 20:47:52 +0000</pubDate>
      <link>https://dev.to/tahsin000/mid-year-backend-reset-my-h2-goals-for-speed-security-and-better-docs-14ap</link>
      <guid>https://dev.to/tahsin000/mid-year-backend-reset-my-h2-goals-for-speed-security-and-better-docs-14ap</guid>
      <description>&lt;p&gt;July always feels like a natural pause point.&lt;/p&gt;

&lt;p&gt;The first half of the year is already behind us. Some features shipped. Some bugs were fixed. Some ideas worked well. A few things probably stayed in the backlog longer than expected.&lt;/p&gt;

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

&lt;p&gt;For me, this is not about making a huge roadmap or setting unrealistic goals. It is more about asking a simple question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What backend systems do I want to make better before the year ends?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After thinking about my recent work, I found myself coming back to three areas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are not flashy goals. They are not always visible to users. But they are the kind of improvements that make a backend codebase healthier, safer, and easier to work with over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Like Doing a Mid-Year Engineering Reset
&lt;/h2&gt;

&lt;p&gt;At the start of the year, goals often feel exciting. We plan new projects, new features, new tools, and new habits.&lt;/p&gt;

&lt;p&gt;But by the middle of the year, reality has already happened.&lt;/p&gt;

&lt;p&gt;Urgent fixes appear. Product priorities change. Some technical debt gets ignored because there is always something more important to ship.&lt;/p&gt;

&lt;p&gt;That is why I like the idea of an H2 engineering reset.&lt;/p&gt;

&lt;p&gt;It gives me a chance to review the systems I work on with a fresh mind. Instead of only asking, “What should we build next?” I can also ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is slowing us down?&lt;/li&gt;
&lt;li&gt;What keeps breaking?&lt;/li&gt;
&lt;li&gt;What is hard to understand?&lt;/li&gt;
&lt;li&gt;What would make the next six months easier?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This kind of reset is useful because backend quality is not built in one big moment. It is built through small, careful improvements repeated over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal 1: Improve Performance
&lt;/h2&gt;

&lt;p&gt;Performance is one of those things that is easy to ignore until users start feeling the pain.&lt;/p&gt;

&lt;p&gt;A page loads a little slower. An API takes a few extra seconds. A database query works fine with 100 records but becomes painful with 100,000 records.&lt;/p&gt;

&lt;p&gt;At first, these issues may not look urgent. But slowly, they make the product feel heavy.&lt;/p&gt;

&lt;p&gt;For the second half of the year, I want to be more intentional about backend performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where I Want to Focus
&lt;/h3&gt;

&lt;p&gt;For Laravel projects, this means looking closely at a few common areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slow database queries&lt;/li&gt;
&lt;li&gt;Missing indexes&lt;/li&gt;
&lt;li&gt;N+1 query problems&lt;/li&gt;
&lt;li&gt;Heavy API responses&lt;/li&gt;
&lt;li&gt;Unnecessary background jobs&lt;/li&gt;
&lt;li&gt;Cacheable data that is being fetched again and again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple example is a dashboard page.&lt;/p&gt;

&lt;p&gt;Maybe the dashboard shows user stats, recent orders, payment data, and notifications. At first, everything works fine. But after a few months, the page starts taking longer to load.&lt;/p&gt;

&lt;p&gt;The problem may not be the whole system. It may be one query that loads too much data, or one relationship that is not eager loaded properly.&lt;/p&gt;

&lt;p&gt;Small fixes can make a big difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Steps I Want to Take
&lt;/h3&gt;

&lt;p&gt;My performance reset will be simple:&lt;/p&gt;

&lt;p&gt;First, I want to identify the slowest endpoints. I do not want to guess. I want to measure.&lt;/p&gt;

&lt;p&gt;Then, I want to review the database queries behind those endpoints. Are they doing too much? Are they using indexes properly? Are they loading relationships in a clean way?&lt;/p&gt;

&lt;p&gt;Finally, I want to use caching where it actually makes sense.&lt;/p&gt;

&lt;p&gt;Not everything needs to be cached. But data that does not change often should not be rebuilt on every request.&lt;/p&gt;

&lt;p&gt;The goal is not to make everything perfect. The goal is to make the most used parts of the system faster and more reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal 2: Strengthen Security
&lt;/h2&gt;

&lt;p&gt;Security is not a one-time task.&lt;/p&gt;

&lt;p&gt;It is not something we finish after adding authentication or installing a package. It needs regular review, especially as an application grows.&lt;/p&gt;

&lt;p&gt;New routes are added. New permissions are created. New integrations are connected. Over time, small gaps can appear.&lt;/p&gt;

&lt;p&gt;That is why security is my second H2 backend goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Areas I Want to Recheck
&lt;/h3&gt;

&lt;p&gt;In Laravel apps, I want to review things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication flow&lt;/li&gt;
&lt;li&gt;Authorization rules&lt;/li&gt;
&lt;li&gt;Role and permission checks&lt;/li&gt;
&lt;li&gt;API token usage&lt;/li&gt;
&lt;li&gt;Form request validation&lt;/li&gt;
&lt;li&gt;File upload handling&lt;/li&gt;
&lt;li&gt;Sensitive data exposure&lt;/li&gt;
&lt;li&gt;Environment configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One real-life situation many developers face is permission logic becoming scattered.&lt;/p&gt;

&lt;p&gt;For example, one controller checks if a user is an admin. Another checks if the user owns the resource. Another uses a policy. Another has the logic written directly inside the method.&lt;/p&gt;

&lt;p&gt;Everything may work, but it becomes harder to trust.&lt;/p&gt;

&lt;p&gt;When permission logic is not consistent, future changes become risky.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Steps I Want to Take
&lt;/h3&gt;

&lt;p&gt;For the second half of the year, I want to clean up authorization logic and move more checks into proper Laravel policies or gates where possible.&lt;/p&gt;

&lt;p&gt;I also want to review validation rules more carefully.&lt;/p&gt;

&lt;p&gt;Good validation is not only about showing nice error messages. It protects the system from bad data, unexpected input, and edge cases.&lt;/p&gt;

&lt;p&gt;Another important step is checking what data gets returned from APIs.&lt;/p&gt;

&lt;p&gt;Sometimes an API response includes more fields than the frontend actually needs. That can accidentally expose internal or sensitive information.&lt;/p&gt;

&lt;p&gt;So the security goal is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make access clear, input strict, and output intentional.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That one sentence is easy to remember, and it covers a lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal 3: Improve Documentation
&lt;/h2&gt;

&lt;p&gt;Documentation is usually the easiest thing to delay.&lt;/p&gt;

&lt;p&gt;When we are busy, we tell ourselves, “I will document this later.”&lt;/p&gt;

&lt;p&gt;But later often becomes never.&lt;/p&gt;

&lt;p&gt;Then after a few months, someone asks:&lt;/p&gt;

&lt;p&gt;“How does this job work?”&lt;br&gt;
“Why does this API behave this way?”&lt;br&gt;
“What happens when this webhook fails?”&lt;br&gt;
“Where is this config coming from?”&lt;/p&gt;

&lt;p&gt;And suddenly, the missing documentation becomes expensive.&lt;/p&gt;

&lt;p&gt;For H2, I want to treat documentation as part of the backend system, not as an extra task.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I Want to Document Better
&lt;/h3&gt;

&lt;p&gt;I do not want to write huge documents that nobody reads. I want useful documentation that helps developers move faster.&lt;/p&gt;

&lt;p&gt;That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API behavior&lt;/li&gt;
&lt;li&gt;Important business rules&lt;/li&gt;
&lt;li&gt;Queue jobs&lt;/li&gt;
&lt;li&gt;Scheduled commands&lt;/li&gt;
&lt;li&gt;Webhook flows&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;li&gt;Setup steps&lt;/li&gt;
&lt;li&gt;Common debugging notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if a payment webhook updates an order status, that flow should be easy to understand.&lt;/p&gt;

&lt;p&gt;A developer should be able to read a short note and know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which event comes from the payment provider&lt;/li&gt;
&lt;li&gt;Which route receives it&lt;/li&gt;
&lt;li&gt;Which job processes it&lt;/li&gt;
&lt;li&gt;Which tables are updated&lt;/li&gt;
&lt;li&gt;What happens if the webhook fails&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This does not need a 20-page document. A clear Markdown file can be enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Steps I Want to Take
&lt;/h3&gt;

&lt;p&gt;My documentation reset will start with the most confusing parts of the system.&lt;/p&gt;

&lt;p&gt;I want to document the areas where I have previously had to explain the same thing more than once. That is usually a good sign that documentation is missing.&lt;/p&gt;

&lt;p&gt;I also want to keep docs close to the code when possible.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API notes inside an &lt;code&gt;/docs&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;Setup instructions in &lt;code&gt;README.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Complex service explanations near the related module&lt;/li&gt;
&lt;li&gt;Short comments only where the code needs context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good documentation does not explain every line of code. It explains the decisions, flows, and important details that are not obvious.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the Reset Realistic
&lt;/h2&gt;

&lt;p&gt;The biggest mistake with planning is trying to fix everything at once.&lt;/p&gt;

&lt;p&gt;That usually leads to frustration.&lt;/p&gt;

&lt;p&gt;So I want to keep this H2 reset small and realistic.&lt;/p&gt;

&lt;p&gt;Instead of saying, “Improve the whole backend,” I can say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimize the top 3 slowest endpoints&lt;/li&gt;
&lt;li&gt;Review authorization for the most sensitive modules&lt;/li&gt;
&lt;li&gt;Document the 5 most confusing backend flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That feels much more doable.&lt;/p&gt;

&lt;p&gt;It also creates visible progress.&lt;/p&gt;

&lt;p&gt;A backend system improves when we choose specific problems and solve them carefully.&lt;/p&gt;

</description>
      <category>backenddevelopment</category>
      <category>laravel</category>
      <category>engineeringgoals</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Redis on Windows with Laragon and Laravel: The PATH Issue That Looks Like a Redis Issue</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Fri, 26 Jun 2026 13:19:09 +0000</pubDate>
      <link>https://dev.to/tahsin000/redis-on-windows-with-laragon-and-laravel-the-path-issue-that-looks-like-a-redis-issue-4omd</link>
      <guid>https://dev.to/tahsin000/redis-on-windows-with-laragon-and-laravel-the-path-issue-that-looks-like-a-redis-issue-4omd</guid>
      <description>&lt;p&gt;A few days ago, I was working on a Laravel project on Windows. The project needed Redis for cache and queue handling, and since I was using Laragon, I thought the setup would be simple.&lt;/p&gt;

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

&lt;p&gt;Laragon already had Redis inside its &lt;code&gt;bin&lt;/code&gt; folder. I started Redis, opened the terminal, and ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect.&lt;/p&gt;

&lt;p&gt;Then I moved to my Laravel project folder, opened Git Bash, and tried the same command again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, I got:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash: redis-cli: &lt;span class="nb"&gt;command &lt;/span&gt;not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, it looked like Redis was not installed properly. Then I wondered if Redis only worked inside Laragon’s &lt;code&gt;www&lt;/code&gt; folder. Maybe my Laravel project was outside the correct directory?&lt;/p&gt;

&lt;p&gt;But the real problem was much simpler.&lt;/p&gt;

&lt;p&gt;It was not a Redis problem.&lt;/p&gt;

&lt;p&gt;It was not a Laravel problem.&lt;/p&gt;

&lt;p&gt;It was not a project folder problem.&lt;/p&gt;

&lt;p&gt;It was a PATH problem.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk through the full Redis setup on Windows using Laragon, how to make &lt;code&gt;redis-cli&lt;/code&gt; work from Git Bash, and how to connect it properly with a Laravel project.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Situation
&lt;/h2&gt;

&lt;p&gt;My Laravel project was not inside Laragon’s default &lt;code&gt;www&lt;/code&gt; folder. It was somewhere like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;C:&lt;span class="se"&gt;\U&lt;/span&gt;sers&lt;span class="se"&gt;\A&lt;/span&gt;sus&lt;span class="se"&gt;\D&lt;/span&gt;ownloads&lt;span class="se"&gt;\a&lt;/span&gt;romablendbd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But Laragon was installed here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;D:&lt;span class="se"&gt;\C&lt;/span&gt;&lt;span class="nt"&gt;-data&lt;/span&gt;&lt;span class="se"&gt;\l&lt;/span&gt;aragon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I opened Laragon’s own terminal or Cmder, this worked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But inside Git Bash from my Laravel project folder, the same command failed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash: redis-cli: &lt;span class="nb"&gt;command &lt;/span&gt;not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where the confusion started.&lt;/p&gt;

&lt;p&gt;Redis itself does not care where your Laravel project is located. Redis runs as a server, usually on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1:6379
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So any project can connect to it, whether the project is inside &lt;code&gt;www&lt;/code&gt;, &lt;code&gt;Downloads&lt;/code&gt;, &lt;code&gt;Desktop&lt;/code&gt;, or another drive.&lt;/p&gt;

&lt;p&gt;The only issue was that Git Bash did not know where &lt;code&gt;redis-cli.exe&lt;/code&gt; was located.&lt;/p&gt;

&lt;p&gt;Laragon’s terminal automatically adds Laragon tools to its PATH. Git Bash does not.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Find the Redis CLI File
&lt;/h2&gt;

&lt;p&gt;First, we need to find the actual &lt;code&gt;redis-cli.exe&lt;/code&gt; file inside Laragon.&lt;/p&gt;

&lt;p&gt;In Git Bash, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /d/C-data/laragon/bin &lt;span class="nt"&gt;-iname&lt;/span&gt; &lt;span class="s2"&gt;"redis-cli.exe"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your Laragon path may be different. For example, if Laragon is installed in &lt;code&gt;C:\laragon&lt;/code&gt;, you may need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /c/laragon/bin &lt;span class="nt"&gt;-iname&lt;/span&gt; &lt;span class="s2"&gt;"redis-cli.exe"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, the result was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/d/C-data/laragon/bin/redis/redis-x64-5.0.14.1/redis-cli.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirmed that Redis CLI was already installed. Git Bash simply could not find it globally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Test Redis Using the Full Path
&lt;/h2&gt;

&lt;p&gt;Before changing PATH settings, it’s always good to test the command directly.&lt;/p&gt;

&lt;p&gt;I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/d/C-data/laragon/bin/redis/redis-x64-5.0.14.1/redis-cli.exe ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the output was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was the important moment.&lt;/p&gt;

&lt;p&gt;It confirmed three things:&lt;/p&gt;

&lt;p&gt;Redis was installed.&lt;/p&gt;

&lt;p&gt;Redis server was running.&lt;/p&gt;

&lt;p&gt;Git Bash could reach Redis when I used the full path.&lt;/p&gt;

&lt;p&gt;So the server was fine. The port was fine. The Laravel folder location was fine.&lt;/p&gt;

&lt;p&gt;Only the command shortcut was missing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Add Redis CLI to Git Bash PATH
&lt;/h2&gt;

&lt;p&gt;To make &lt;code&gt;redis-cli&lt;/code&gt; available from any folder in Git Bash, I added the Redis folder to &lt;code&gt;~/.bashrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the command I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="$PATH:/d/C-data/laragon/bin/redis/redis-x64-5.0.14.1"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, I tested again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, it worked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I could run &lt;code&gt;redis-cli&lt;/code&gt; from any folder, including my Laravel project folder.&lt;/p&gt;

&lt;p&gt;This is the clean fix for the &lt;code&gt;redis-cli: command not found&lt;/code&gt; issue in Git Bash.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Small Redis CLI Mistake That Can Confuse You
&lt;/h2&gt;

&lt;p&gt;At one point, I entered the Redis shell by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the terminal changed to something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;127.0.0.1:6379&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside this prompt, I tried:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was wrong.&lt;/p&gt;

&lt;p&gt;When you are inside the Redis shell, you should only write Redis commands.&lt;/p&gt;

&lt;p&gt;Correct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wrong:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;redis-cli&lt;/code&gt; is a terminal command. It starts the Redis command-line tool.&lt;/p&gt;

&lt;p&gt;But once you are already inside Redis CLI, you only need to type Redis commands like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping
&lt;span class="nb"&gt;set &lt;/span&gt;name laragon
get name
&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So there are two valid ways to test Redis.&lt;/p&gt;

&lt;p&gt;From the normal terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or from inside the Redis shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both are correct, but they are used in different places.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Make Sure Redis Server Is Running
&lt;/h2&gt;

&lt;p&gt;If you installed the full version of Laragon, Redis is usually included inside the Laragon &lt;code&gt;bin&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;A common Redis path looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;C:&lt;span class="se"&gt;\l&lt;/span&gt;aragon&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;edis&lt;span class="se"&gt;\r&lt;/span&gt;edis-x64-3.2.100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or in my case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;D:&lt;span class="se"&gt;\C&lt;/span&gt;&lt;span class="nt"&gt;-data&lt;/span&gt;&lt;span class="se"&gt;\l&lt;/span&gt;aragon&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;edis&lt;span class="se"&gt;\r&lt;/span&gt;edis-x64-5.0.14.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can start Redis by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-server.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or from Git Bash, using the full path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/d/C-data/laragon/bin/redis/redis-x64-5.0.14.1/redis-server.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the Redis server is running, keep that terminal open.&lt;/p&gt;

&lt;p&gt;To stop the server later, press:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Ctrl + C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laragon may also let you manage Redis from its menu depending on your installation.&lt;/p&gt;

&lt;p&gt;One important note: Redis native Windows support is limited, and many Windows setups use older Redis builds. For the latest Redis versions, Docker, WSL, or Laradock can be a better option. But for local Laravel development, Laragon’s Redis works well enough in many cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Configure Laravel &lt;code&gt;.env&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;After Redis worked in the terminal, the next step was Laravel.&lt;/p&gt;

&lt;p&gt;In the Laravel project, I opened the &lt;code&gt;.env&lt;/code&gt; file and checked the Redis settings.&lt;/p&gt;

&lt;p&gt;For my setup, I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REDIS_CLIENT=predis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to use Redis for cache, also check your cache setting.&lt;/p&gt;

&lt;p&gt;For newer Laravel versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CACHE_STORE=redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For older Laravel versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CACHE_DRIVER=redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key point is this:&lt;/p&gt;

&lt;p&gt;Laravel does not need the &lt;code&gt;redis-cli&lt;/code&gt; command to connect to Redis.&lt;/p&gt;

&lt;p&gt;Laravel connects to Redis through PHP using the host and port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1:6379
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So even if &lt;code&gt;redis-cli&lt;/code&gt; was not available in Git Bash, Laravel could still connect if the Redis client package or PHP extension was correctly installed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Install Laravel Dependencies
&lt;/h2&gt;

&lt;p&gt;If this is an existing Laravel project, run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This installs the dependencies listed in &lt;code&gt;composer.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In my case, Laravel was configured to use Predis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REDIS_CLIENT=predis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But when I tested Redis in Laravel, I got this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class "Predis\Client" not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means Laravel wanted to use Predis, but the package was not installed.&lt;/p&gt;

&lt;p&gt;The fix was simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require predis/predis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing Predis, I cleared Laravel’s cached config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan config:clear
php artisan cache:clear
php artisan optimize:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step is important because Laravel may keep old &lt;code&gt;.env&lt;/code&gt; or config values in cache.&lt;/p&gt;




&lt;h2&gt;
  
  
  Predis vs PhpRedis
&lt;/h2&gt;

&lt;p&gt;Laravel can use Redis in two common ways.&lt;/p&gt;

&lt;p&gt;The first option is Predis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REDIS_CLIENT=predis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this, install the Composer package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require predis/predis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is often the easiest option when you are working on Windows and want a quick local setup.&lt;/p&gt;

&lt;p&gt;The second option is PhpRedis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REDIS_CLIENT=phpredis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this, you need the PHP Redis extension enabled.&lt;/p&gt;

&lt;p&gt;In Laragon, the Redis PHP extension does not always come enabled by default. You may need to download the correct &lt;code&gt;php_redis.dll&lt;/code&gt; file that matches your PHP version, architecture, and thread-safety build.&lt;/p&gt;

&lt;p&gt;You can check your PHP version from Laragon. Then download the matching Redis extension DLL from PECL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://pecl.php.net/package/redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After downloading, copy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php_redis.dll
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Into your PHP extension folder, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;C:&lt;span class="se"&gt;\l&lt;/span&gt;aragon&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\p&lt;/span&gt;hp&lt;span class="se"&gt;\p&lt;/span&gt;hp-8.x.x&lt;span class="se"&gt;\e&lt;/span&gt;xt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add this line to your &lt;code&gt;php.ini&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;php_redis.dll&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Laragon after making the change.&lt;/p&gt;

&lt;p&gt;For many local projects, Predis is simpler. For better performance in some production setups, PhpRedis is commonly used.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Test Redis from Laravel Tinker
&lt;/h2&gt;

&lt;p&gt;Now came the final test.&lt;/p&gt;

&lt;p&gt;From the Laravel project folder, I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan optimize:clear
php artisan tinker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside Tinker, I first tried:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Redis&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I got:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class "Redis" not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does not always mean Redis is broken. It can simply mean the Redis facade was not imported in Tinker.&lt;/p&gt;

&lt;p&gt;The safer way is to use the full namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;\Illuminate\Support\Facades\Redis&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use Laravel’s service container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'redis'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s2"&gt;"PONG"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I saw &lt;code&gt;"PONG"&lt;/code&gt; from Laravel Tinker, the setup was finally complete.&lt;/p&gt;

&lt;p&gt;At that point, Redis was working in three places:&lt;/p&gt;

&lt;p&gt;From Laragon terminal.&lt;/p&gt;

&lt;p&gt;From Git Bash.&lt;/p&gt;

&lt;p&gt;From Laravel itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Errors and What They Really Mean
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;bash: redis-cli: command not found&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This means your terminal cannot find &lt;code&gt;redis-cli.exe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It does not mean Redis is not installed.&lt;/p&gt;

&lt;p&gt;Fix it by adding the Redis folder to Git Bash PATH:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="$PATH:/d/C-data/laragon/bin/redis/redis-x64-5.0.14.1"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;code&gt;Class "Predis\Client" not found&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This means Laravel is using Predis, but the package is missing.&lt;/p&gt;

&lt;p&gt;Fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require predis/predis
php artisan optimize:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;code&gt;Class "Redis" not found&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This may happen in Tinker when the Redis facade is not imported.&lt;/p&gt;

&lt;p&gt;Use the full namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;\Illuminate\Support\Facades\Redis&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'redis'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Redis Works in &lt;code&gt;www&lt;/code&gt; but Not in Another Folder
&lt;/h3&gt;

&lt;p&gt;This is usually not a folder issue.&lt;/p&gt;

&lt;p&gt;Laragon terminal automatically sets PATH for Laragon tools. Git Bash does not.&lt;/p&gt;

&lt;p&gt;Redis runs on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;127.0.0.1:6379
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So your Laravel project can be anywhere as long as Redis is running and Laravel is configured correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Working Setup
&lt;/h2&gt;

&lt;p&gt;Here is the final setup that worked for me.&lt;/p&gt;

&lt;p&gt;Redis CLI path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/d/C-data/laragon/bin/redis/redis-x64-5.0.14.1/redis-cli.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git Bash PATH fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="$PATH:/d/C-data/laragon/bin/redis/redis-x64-5.0.14.1"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Redis terminal test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REDIS_CLIENT=predis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
CACHE_STORE=redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Predis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require predis/predis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clear Laravel config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan config:clear
php artisan cache:clear
php artisan optimize:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test in Tinker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan tinker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;\Illuminate\Support\Facades\Redis&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s2"&gt;"PONG"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>php</category>
      <category>windows</category>
      <category>redis</category>
      <category>laravel</category>
    </item>
    <item>
      <title>How to Create a GitHub Pull Request from the Terminal</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Tue, 23 Jun 2026 09:04:54 +0000</pubDate>
      <link>https://dev.to/tahsin000/how-to-create-a-github-pull-request-from-the-terminal-3a0g</link>
      <guid>https://dev.to/tahsin000/how-to-create-a-github-pull-request-from-the-terminal-3a0g</guid>
      <description>&lt;p&gt;Pull Requests are a normal part of working with GitHub. You write code in a branch, push it to GitHub, then open a Pull Request so your team can review and merge it.&lt;/p&gt;

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

&lt;p&gt;Most developers create Pull Requests from the GitHub website. That works fine.&lt;/p&gt;

&lt;p&gt;But once you get comfortable with the terminal, you can do the whole flow without leaving your editor or command line.&lt;/p&gt;

&lt;p&gt;In this post, we will go through a simple and practical workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;update your local &lt;code&gt;main&lt;/code&gt; branch&lt;/li&gt;
&lt;li&gt;create a new feature branch&lt;/li&gt;
&lt;li&gt;commit your changes&lt;/li&gt;
&lt;li&gt;push the branch to GitHub&lt;/li&gt;
&lt;li&gt;create a Pull Request from the terminal using GitHub CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s use a real example: you are building a login page.&lt;/p&gt;




&lt;h2&gt;
  
  
  First, Know the Difference: &lt;code&gt;git pull&lt;/code&gt; vs Pull Request
&lt;/h2&gt;

&lt;p&gt;A lot of beginners get confused here.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git pull&lt;/code&gt; and Pull Request are not the same thing.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;git pull&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;git pull&lt;/code&gt; means you are taking the latest code from GitHub and bringing it into your local project.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This updates your local branch with the latest code from the remote &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pull Request
&lt;/h3&gt;

&lt;p&gt;A Pull Request means you are asking to merge your branch changes into another branch, usually &lt;code&gt;main&lt;/code&gt; or &lt;code&gt;develop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So the simple idea is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git pull  = bring latest code to your computer
Pull Request = ask to merge your code into main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a Pull Request from the terminal, the usual flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;push your branch → create PR with GitHub CLI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 1: Update Your Main Branch
&lt;/h2&gt;

&lt;p&gt;Before starting new work, always get the latest code from the main branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout main
git pull origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps you avoid working on old code.&lt;/p&gt;

&lt;p&gt;Think of it like this: before building your new feature, you are making sure your project is fresh and up to date.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Create a New Branch
&lt;/h2&gt;

&lt;p&gt;Now create a new branch for your work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature/login-page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;feature/login-page&lt;/code&gt; is your working branch.&lt;/p&gt;

&lt;p&gt;Good branch names are short, clear, and meaningful.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;feature/navbar
fix/login-error
update/readme
feature/login-page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A clear branch name helps your teammates understand what you are working on before they even open the code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Make Your Code Changes
&lt;/h2&gt;

&lt;p&gt;Now do your actual work.&lt;/p&gt;

&lt;p&gt;For example, you may add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a login page layout&lt;/li&gt;
&lt;li&gt;email and password fields&lt;/li&gt;
&lt;li&gt;a submit button&lt;/li&gt;
&lt;li&gt;basic styling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After changing the code, check the current Git status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows which files were changed, added, or deleted.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Add Your Files
&lt;/h2&gt;

&lt;p&gt;To add all changed files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.&lt;/code&gt; means Git will add all changed files in the current project.&lt;/p&gt;

&lt;p&gt;If you only want to add one file, use the file path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add src/App.jsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful when you changed many files but only want to commit some of them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Commit Your Changes
&lt;/h2&gt;

&lt;p&gt;Now create a commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add login page UI"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A good commit message should be short but clear.&lt;/p&gt;

&lt;p&gt;Good examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Fix navbar responsiveness"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Update README installation steps"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add user login form"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Avoid unclear messages like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"changes"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"update"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your future self and your teammates will thank you for writing clear commit messages.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Push Your Branch to GitHub
&lt;/h2&gt;

&lt;p&gt;Now push your branch to GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin feature/login-page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also push the current branch like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very handy because you do not need to type the full branch name.&lt;/p&gt;

&lt;p&gt;After this, your local branch exists on GitHub too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Install GitHub CLI
&lt;/h2&gt;

&lt;p&gt;To create a Pull Request from the terminal, you need GitHub CLI.&lt;/p&gt;

&lt;p&gt;GitHub CLI gives you the &lt;code&gt;gh&lt;/code&gt; command.&lt;/p&gt;

&lt;h3&gt;
  
  
  On Windows
&lt;/h3&gt;

&lt;p&gt;Open PowerShell or Windows Terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;winget &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--id&lt;/span&gt; GitHub.cli &lt;span class="nt"&gt;--source&lt;/span&gt; winget
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing, close the terminal and open a new one.&lt;/p&gt;

&lt;p&gt;Then check:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  On macOS
&lt;/h3&gt;

&lt;p&gt;If you use Homebrew, run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then check:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you see the version number, GitHub CLI is installed correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 8: Login to GitHub CLI
&lt;/h2&gt;

&lt;p&gt;You only need to do this once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see some options. In most cases, choose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GitHub.com
HTTPS
Yes
Login with a web browser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A browser window may open for login and authorization.&lt;/p&gt;

&lt;p&gt;After login, check if everything is working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh auth status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you are logged in, you can create Pull Requests from the terminal without opening the GitHub website.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 9: Create a Pull Request from the Terminal
&lt;/h2&gt;

&lt;p&gt;The easiest way is interactive mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub CLI will ask you questions like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Title:
Body:
Base branch:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The base branch is usually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, if your team uses &lt;code&gt;develop&lt;/code&gt;, then use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;develop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you answer the questions, GitHub CLI creates the Pull Request and shows you the PR URL.&lt;/p&gt;




&lt;h2&gt;
  
  
  Create a Pull Request in One Command
&lt;/h2&gt;

&lt;p&gt;You can also create the Pull Request in one line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;create &lt;span class="nt"&gt;--base&lt;/span&gt; main &lt;span class="nt"&gt;--head&lt;/span&gt; feature/login-page &lt;span class="nt"&gt;--title&lt;/span&gt; &lt;span class="s2"&gt;"Add login page UI"&lt;/span&gt; &lt;span class="nt"&gt;--body&lt;/span&gt; &lt;span class="s2"&gt;"This PR adds the login page UI with form fields and basic styling."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s understand this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--base main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the branch where you want to merge your code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--head feature/login-page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is your feature branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--title
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the Pull Request title.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--body
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the Pull Request description.&lt;/p&gt;

&lt;p&gt;If you are already inside the feature branch, you can skip &lt;code&gt;--head&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;create &lt;span class="nt"&gt;--base&lt;/span&gt; main &lt;span class="nt"&gt;--title&lt;/span&gt; &lt;span class="s2"&gt;"Add login page UI"&lt;/span&gt; &lt;span class="nt"&gt;--body&lt;/span&gt; &lt;span class="s2"&gt;"This PR adds the login page UI with form fields and basic styling."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Should You Write in a Pull Request?
&lt;/h2&gt;

&lt;p&gt;A good Pull Request should explain two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What changed?&lt;/li&gt;
&lt;li&gt;How did you test it?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is a simple example.&lt;/p&gt;

&lt;h3&gt;
  
  
  PR Title
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add login page UI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  PR Body
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Summary&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Added login page layout
&lt;span class="p"&gt;-&lt;/span&gt; Added email and password input fields
&lt;span class="p"&gt;-&lt;/span&gt; Added submit button styling

&lt;span class="gu"&gt;## Testing&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Ran the app locally
&lt;span class="p"&gt;-&lt;/span&gt; Checked the login page in browser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is clear, professional, and easy to review.&lt;/p&gt;

&lt;p&gt;Your reviewer does not need to guess what you did.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Way to Write a Multiline PR Body
&lt;/h2&gt;

&lt;p&gt;Sometimes you want a clean Pull Request body with headings and bullet points.&lt;/p&gt;

&lt;p&gt;You may try to paste multiline Markdown directly inside &lt;code&gt;--body&lt;/code&gt;, but different shells can behave differently.&lt;/p&gt;

&lt;p&gt;The safest and cleanest way is to use a body file.&lt;/p&gt;

&lt;p&gt;Create a file named:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pr-body.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put it in your project root directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-project/
├── src/
├── public/
├── package.json
├── README.md
└── pr-body.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;pr-body.md&lt;/code&gt;, write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Summary&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Added login page layout
&lt;span class="p"&gt;-&lt;/span&gt; Added email and password fields
&lt;span class="p"&gt;-&lt;/span&gt; Added submit button styling

&lt;span class="gu"&gt;## Testing&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Ran the app locally
&lt;span class="p"&gt;-&lt;/span&gt; Checked login page in browser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create the Pull Request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;create &lt;span class="nt"&gt;--base&lt;/span&gt; main &lt;span class="nt"&gt;--head&lt;/span&gt; feature/login-page &lt;span class="nt"&gt;--title&lt;/span&gt; &lt;span class="s2"&gt;"Add login page UI"&lt;/span&gt; &lt;span class="nt"&gt;--body-file&lt;/span&gt; pr-body.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is usually the best option for real projects.&lt;/p&gt;

&lt;p&gt;It keeps your command clean and your PR description easy to edit.&lt;/p&gt;

&lt;p&gt;After creating the Pull Request, you can delete &lt;code&gt;pr-body.md&lt;/code&gt; if you do not want to keep it in the project.&lt;/p&gt;




&lt;h2&gt;
  
  
  One-Line Multiline Body Without a File
&lt;/h2&gt;

&lt;p&gt;If you really want to write the body directly in the command, here are safe options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bash, Git Bash, or macOS Terminal
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;create &lt;span class="nt"&gt;--base&lt;/span&gt; main &lt;span class="nt"&gt;--head&lt;/span&gt; feature/login-page &lt;span class="nt"&gt;--title&lt;/span&gt; &lt;span class="s2"&gt;"Add login page UI"&lt;/span&gt; &lt;span class="nt"&gt;--body&lt;/span&gt; &lt;span class="s1"&gt;$'## Summary&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;- Added login page layout&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;- Added email and password fields&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;## Testing&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;- Ran the app locally&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;- Checked login page in browser'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;\n&lt;/code&gt; means a new line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Windows PowerShell
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;gh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;feature/login-page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Add login page UI"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"## Summary&lt;/span&gt;&lt;span class="se"&gt;`n&lt;/span&gt;&lt;span class="s2"&gt;- Added login page layout&lt;/span&gt;&lt;span class="se"&gt;`n&lt;/span&gt;&lt;span class="s2"&gt;- Added email and password fields&lt;/span&gt;&lt;span class="se"&gt;`n`n&lt;/span&gt;&lt;span class="s2"&gt;## Testing&lt;/span&gt;&lt;span class="se"&gt;`n&lt;/span&gt;&lt;span class="s2"&gt;- Ran the app locally&lt;/span&gt;&lt;span class="se"&gt;`n&lt;/span&gt;&lt;span class="s2"&gt;- Checked login page in browser"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In PowerShell, newline is written as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still, for most real work, I recommend using &lt;code&gt;--body-file&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is simpler and less error-prone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Check Your Pull Request
&lt;/h2&gt;

&lt;p&gt;After creating the Pull Request, you can check its status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see Pull Requests in the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To view the current branch’s Pull Request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;view
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To open it in the browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;view &lt;span class="nt"&gt;--web&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Opening the browser is optional. You do not need it to create the PR.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Full Practical Workflow
&lt;/h2&gt;

&lt;p&gt;Here is the complete flow you can use every day:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout main
git pull origin main

git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature/my-work

&lt;span class="c"&gt;# after code changes&lt;/span&gt;
git status
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add my work"&lt;/span&gt;
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin HEAD

gh &lt;span class="nb"&gt;pr &lt;/span&gt;create &lt;span class="nt"&gt;--base&lt;/span&gt; main &lt;span class="nt"&gt;--title&lt;/span&gt; &lt;span class="s2"&gt;"Add my work"&lt;/span&gt; &lt;span class="nt"&gt;--body&lt;/span&gt; &lt;span class="s2"&gt;"Added my work and tested locally."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a cleaner Pull Request body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;create &lt;span class="nt"&gt;--base&lt;/span&gt; main &lt;span class="nt"&gt;--title&lt;/span&gt; &lt;span class="s2"&gt;"Add my work"&lt;/span&gt; &lt;span class="nt"&gt;--body-file&lt;/span&gt; pr-body.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the core workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Problems and Fixes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem 1: &lt;code&gt;gh: command not found&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This means GitHub CLI is not installed, or your terminal has not refreshed yet.&lt;/p&gt;

&lt;p&gt;On Windows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;winget &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--id&lt;/span&gt; GitHub.cli &lt;span class="nt"&gt;--source&lt;/span&gt; winget
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then close the terminal and open it again.&lt;/p&gt;

&lt;p&gt;On macOS:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then check:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  Problem 2: You Are Not Logged In
&lt;/h3&gt;

&lt;p&gt;If you see a message saying you are not logged in, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh auth status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Problem 3: Current Branch Is Not Pushed
&lt;/h3&gt;

&lt;p&gt;If GitHub CLI says your branch is not pushed yet, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then try again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Problem 4: Pull Request Is Created from the Wrong Branch
&lt;/h3&gt;

&lt;p&gt;First, check your current branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &lt;span class="nt"&gt;--show-current&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are on the wrong branch, switch to the correct one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout feature/login-page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create the Pull Request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;create &lt;span class="nt"&gt;--base&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






</description>
      <category>git</category>
      <category>github</category>
      <category>cli</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Stop Guessing in Controllers: Debug MySQL Directly</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Wed, 20 May 2026 21:33:32 +0000</pubDate>
      <link>https://dev.to/tahsin000/stop-putting-dd-everywhere-debug-the-database-from-the-source-instead-4n8o</link>
      <guid>https://dev.to/tahsin000/stop-putting-dd-everywhere-debug-the-database-from-the-source-instead-4n8o</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrsm9ndz7n8osm2hi1wt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrsm9ndz7n8osm2hi1wt.png" alt="diagram" width="800" height="878"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every backend developer has done this at some point.&lt;/p&gt;

&lt;p&gt;A request fails.&lt;/p&gt;

&lt;p&gt;Something is not inserting into the database.&lt;/p&gt;

&lt;p&gt;And suddenly the codebase turns into this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nf"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$campaign&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You add logs in controllers.&lt;/p&gt;

&lt;p&gt;Then services.&lt;/p&gt;

&lt;p&gt;Then repositories.&lt;/p&gt;

&lt;p&gt;Then queue workers.&lt;/p&gt;

&lt;p&gt;Then event listeners.&lt;/p&gt;

&lt;p&gt;And after two hours, you are still confused.&lt;/p&gt;

&lt;p&gt;Because the real problem is not where you are looking.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Day I Realized Controller Debugging Wasn’t Enough
&lt;/h2&gt;

&lt;p&gt;A few months ago, a developer on a team I worked with faced a strange issue.&lt;/p&gt;

&lt;p&gt;A simple form submission was supposed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a user&lt;/li&gt;
&lt;li&gt;assign a campaign&lt;/li&gt;
&lt;li&gt;generate a lead&lt;/li&gt;
&lt;li&gt;push a welcome email into queue&lt;/li&gt;
&lt;li&gt;write an activity log&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pretty normal workflow.&lt;/p&gt;

&lt;p&gt;But randomly, some users were being created without campaign data.&lt;/p&gt;

&lt;p&gt;Sometimes the queue job worked.&lt;/p&gt;

&lt;p&gt;Sometimes it didn’t.&lt;/p&gt;

&lt;p&gt;Sometimes the transaction rolled back silently.&lt;/p&gt;

&lt;p&gt;The first reaction?&lt;/p&gt;

&lt;p&gt;Start adding logs everywhere.&lt;/p&gt;

&lt;p&gt;Inside controllers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Controller hit'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Campaign assigned'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside queue workers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Email queued'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside transactions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;beginTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code became a forest of debugging statements.&lt;/p&gt;

&lt;p&gt;Still no clear answer.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Problem
&lt;/h2&gt;

&lt;p&gt;Here’s what most developers forget:&lt;/p&gt;

&lt;p&gt;No matter how beautiful your architecture is…&lt;/p&gt;

&lt;p&gt;No matter whether you use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laravel&lt;/li&gt;
&lt;li&gt;Raw PHP&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end of the day, every query goes to one place:&lt;/p&gt;

&lt;p&gt;MySQL.&lt;/p&gt;

&lt;p&gt;Always.&lt;/p&gt;

&lt;p&gt;Your application is just the messenger.&lt;/p&gt;

&lt;p&gt;The database sees everything.&lt;/p&gt;

&lt;p&gt;That realization changes how you debug systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Instead of Guessing, Watch the Database Directly
&lt;/h2&gt;

&lt;p&gt;The moment we enabled MySQL General Query Log, everything became obvious.&lt;/p&gt;

&lt;p&gt;We literally watched the queries execute live.&lt;/p&gt;

&lt;p&gt;One terminal command showed the full story.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/lib/mysql/hostname.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And suddenly we could see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;campaigns&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;ROLLBACK&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last line explained everything.&lt;/p&gt;

&lt;p&gt;The transaction was rolling back because another process locked a table for a few seconds.&lt;/p&gt;

&lt;p&gt;No controller log would have shown the full picture that clearly.&lt;/p&gt;




&lt;h2&gt;
  
  
  This Is Why Framework-Level Debugging Often Fails
&lt;/h2&gt;

&lt;p&gt;Modern applications are no longer simple.&lt;/p&gt;

&lt;p&gt;A single request may involve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;queues&lt;/li&gt;
&lt;li&gt;events&lt;/li&gt;
&lt;li&gt;transactions&lt;/li&gt;
&lt;li&gt;scheduled jobs&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;background workers&lt;/li&gt;
&lt;li&gt;third-party APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the time you debug from inside the controller, the actual issue may already be happening somewhere else entirely.&lt;/p&gt;

&lt;p&gt;This is why developers sometimes spend hours debugging “application logic” when the real problem is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a deadlock&lt;/li&gt;
&lt;li&gt;a lock wait&lt;/li&gt;
&lt;li&gt;a slow query&lt;/li&gt;
&lt;li&gt;missing index&lt;/li&gt;
&lt;li&gt;rollback&lt;/li&gt;
&lt;li&gt;transaction conflict&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And MySQL already knows all of this.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Most Useful MySQL Debugging Tools
&lt;/h2&gt;

&lt;p&gt;Honestly, there are four MySQL features every backend developer should know.&lt;/p&gt;

&lt;p&gt;Not just DBAs.&lt;/p&gt;

&lt;p&gt;Actual application developers.&lt;/p&gt;

&lt;p&gt;Because these tools solve real-world production headaches.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. General Query Log
&lt;/h2&gt;

&lt;p&gt;See everything.&lt;/p&gt;

&lt;p&gt;This is the closest thing to “watching the database think.”&lt;/p&gt;

&lt;p&gt;Enable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every query gets logged.&lt;/p&gt;

&lt;p&gt;You can literally submit a form and watch the database flow in real time.&lt;/p&gt;

&lt;p&gt;This becomes incredibly useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one request touches multiple tables&lt;/li&gt;
&lt;li&gt;transactions fail&lt;/li&gt;
&lt;li&gt;duplicate queries happen&lt;/li&gt;
&lt;li&gt;hidden queries execute behind ORM magic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Especially in large Laravel applications where Eloquent sometimes hides too much.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Slow Query Log
&lt;/h2&gt;

&lt;p&gt;Find hidden performance problems.&lt;/p&gt;

&lt;p&gt;This one saves applications.&lt;/p&gt;

&lt;p&gt;Seriously.&lt;/p&gt;

&lt;p&gt;Sometimes developers optimize controllers endlessly while the real problem is one terrible query.&lt;/p&gt;

&lt;p&gt;Enable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;slow_query_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;long_query_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now MySQL logs anything slower than one second.&lt;/p&gt;

&lt;p&gt;This helps identify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing indexes&lt;/li&gt;
&lt;li&gt;N+1 problems&lt;/li&gt;
&lt;li&gt;huge scans&lt;/li&gt;
&lt;li&gt;inefficient joins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I once saw a dashboard drop from 12 seconds to under 800ms just because a slow query log exposed a missing index.&lt;/p&gt;

&lt;p&gt;The application code itself was completely fine.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. InnoDB Status
&lt;/h2&gt;

&lt;p&gt;Understand deadlocks &amp;amp; locks.&lt;/p&gt;

&lt;p&gt;This command feels like magic the first time you use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;ENGINE&lt;/span&gt; &lt;span class="n"&gt;INNODB&lt;/span&gt; &lt;span class="n"&gt;STATUS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your application ever experiences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hanging requests&lt;/li&gt;
&lt;li&gt;frozen queues&lt;/li&gt;
&lt;li&gt;stuck inserts&lt;/li&gt;
&lt;li&gt;transaction conflicts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This command can immediately reveal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LATEST DETECTED DEADLOCK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOCK WAIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And suddenly the mystery disappears.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. General Log Table Audit
&lt;/h2&gt;

&lt;p&gt;This is where debugging becomes much more practical.&lt;/p&gt;

&lt;p&gt;Most developers enable General Query Log and only think about the log file.&lt;/p&gt;

&lt;p&gt;But MySQL can also write general logs into a table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means you can inspect logs using normal SQL.&lt;/p&gt;

&lt;p&gt;You can filter by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;latest queries&lt;/li&gt;
&lt;li&gt;specific table name&lt;/li&gt;
&lt;li&gt;specific command type&lt;/li&gt;
&lt;li&gt;specific MySQL thread ID&lt;/li&gt;
&lt;li&gt;insert/update/delete queries&lt;/li&gt;
&lt;li&gt;commit or rollback queries&lt;/li&gt;
&lt;li&gt;transaction flow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is much better than randomly placing &lt;code&gt;Log::info()&lt;/code&gt; everywhere.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisite: Make Sure General Log Writes to Table
&lt;/h2&gt;

&lt;p&gt;Before querying &lt;code&gt;mysql.general_log&lt;/code&gt;, check where MySQL is writing logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;VARIABLES&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'log_output'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;VARIABLES&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'general_log'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;log_output&lt;/code&gt; is only &lt;code&gt;FILE&lt;/code&gt;, logs will go to a file.&lt;/p&gt;

&lt;p&gt;If you want to query logs from a table, enable table output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;log_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'TABLE'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want both file and table logging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;log_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'TABLE,FILE'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now MySQL will write General Query Log entries into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important note:&lt;/p&gt;

&lt;p&gt;You need enough MySQL permission to run &lt;code&gt;SET GLOBAL&lt;/code&gt; and read from &lt;code&gt;mysql.general_log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is usually something you do in a local, staging, or temporary production debugging session with proper access.&lt;/p&gt;




&lt;h2&gt;
  
  
  View Latest Queries from General Log Table
&lt;/h2&gt;

&lt;p&gt;Once General Query Log is enabled with table output, you can inspect the latest queries like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you the real database activity.&lt;/p&gt;

&lt;p&gt;Not what you think Laravel executed.&lt;/p&gt;

&lt;p&gt;Not what your controller expected.&lt;/p&gt;

&lt;p&gt;Not what your service class assumed.&lt;/p&gt;

&lt;p&gt;What MySQL actually received.&lt;/p&gt;




&lt;h2&gt;
  
  
  Filter Only Actual SQL Queries
&lt;/h2&gt;

&lt;p&gt;The general log contains different command types.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Connect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Query&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Prepare&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Execute&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Quit&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of the time, you only care about actual SQL statements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;command_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Query'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This removes connection noise and focuses on real queries.&lt;/p&gt;




&lt;h2&gt;
  
  
  Find Queries for a Specific Table
&lt;/h2&gt;

&lt;p&gt;Suppose your issue is related to the &lt;code&gt;users&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;You can filter only queries that touched &lt;code&gt;users&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%users%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For campaign-related debugging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%campaigns%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is extremely useful when one request touches multiple tables.&lt;/p&gt;

&lt;p&gt;For example, one form submission may touch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;users&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;campaigns&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;leads&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;jobs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;activity_logs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of checking five different PHP files, you can ask MySQL directly:&lt;/p&gt;

&lt;p&gt;“What happened to this table?”&lt;/p&gt;




&lt;h2&gt;
  
  
  Check Only INSERT Queries
&lt;/h2&gt;

&lt;p&gt;If your form submission is supposed to create a user, check whether the &lt;code&gt;INSERT&lt;/code&gt; query actually reached MySQL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;command_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Query'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'INSERT%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specific table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;command_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Query'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'INSERT%'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%users%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can answer important questions:&lt;/p&gt;

&lt;p&gt;Did the insert query happen?&lt;/p&gt;

&lt;p&gt;Did it happen once?&lt;/p&gt;

&lt;p&gt;Did it happen multiple times?&lt;/p&gt;

&lt;p&gt;Did it happen before rollback?&lt;/p&gt;

&lt;p&gt;Did another process insert something unexpectedly?&lt;/p&gt;

&lt;p&gt;That is the kind of answer controller logs often fail to provide.&lt;/p&gt;




&lt;h2&gt;
  
  
  Check UPDATE and DELETE Queries
&lt;/h2&gt;

&lt;p&gt;For update issues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;command_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Query'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'UPDATE%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For delete issues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;command_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Query'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'DELETE%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a specific table update:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;command_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Query'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'UPDATE%'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%campaigns%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps you catch accidental updates or deletes triggered by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;model observers&lt;/li&gt;
&lt;li&gt;queue jobs&lt;/li&gt;
&lt;li&gt;event listeners&lt;/li&gt;
&lt;li&gt;cron jobs&lt;/li&gt;
&lt;li&gt;scheduled commands&lt;/li&gt;
&lt;li&gt;background workers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Check COMMIT and ROLLBACK
&lt;/h2&gt;

&lt;p&gt;This is one of the most important parts.&lt;/p&gt;

&lt;p&gt;Sometimes the query runs successfully.&lt;/p&gt;

&lt;p&gt;But the transaction rolls back later.&lt;/p&gt;

&lt;p&gt;To check transaction result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'commit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rollback'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ROLLBACK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after your insert or update queries, then your problem is not the insert query itself.&lt;/p&gt;

&lt;p&gt;Your problem is somewhere inside the transaction.&lt;/p&gt;

&lt;p&gt;Maybe an exception happened.&lt;/p&gt;

&lt;p&gt;Maybe a lock wait happened.&lt;/p&gt;

&lt;p&gt;Maybe another process created a conflict.&lt;/p&gt;

&lt;p&gt;Maybe a queue or event triggered something unexpected.&lt;/p&gt;

&lt;p&gt;This is exactly why debugging only from the controller is not enough.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trace One Request Using Thread ID
&lt;/h2&gt;

&lt;p&gt;This is where things become really powerful.&lt;/p&gt;

&lt;p&gt;Every MySQL connection has a &lt;code&gt;thread_id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you find one suspicious query, copy its &lt;code&gt;thread_id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then filter the full flow for that connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;thread_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can see the query sequence in order.&lt;/p&gt;

&lt;p&gt;Example output may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;campaigns&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;leads&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;ROLLBACK&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tells the real story.&lt;/p&gt;

&lt;p&gt;Not guesswork.&lt;/p&gt;

&lt;p&gt;Not random logs.&lt;/p&gt;

&lt;p&gt;The actual database flow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trace Transaction Start, Commit, and Rollback
&lt;/h2&gt;

&lt;p&gt;If you only want transaction-related statements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'start transaction%'&lt;/span&gt;
   &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'begin'&lt;/span&gt;
   &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'commit'&lt;/span&gt;
   &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'rollback'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a specific thread:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;thread_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'start transaction%'&lt;/span&gt;
        &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'begin'&lt;/span&gt;
        &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'commit'&lt;/span&gt;
        &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'rollback'&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very useful when a form submission works sometimes and fails randomly.&lt;/p&gt;

&lt;p&gt;Because now you can see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;when the transaction started&lt;/li&gt;
&lt;li&gt;which queries happened inside it&lt;/li&gt;
&lt;li&gt;whether it committed&lt;/li&gt;
&lt;li&gt;whether it rolled back&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Can We Filter POST Requests from MySQL?
&lt;/h2&gt;

&lt;p&gt;Not directly.&lt;/p&gt;

&lt;p&gt;MySQL does not know whether the original HTTP request was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GET&lt;/li&gt;
&lt;li&gt;POST&lt;/li&gt;
&lt;li&gt;PUT&lt;/li&gt;
&lt;li&gt;PATCH&lt;/li&gt;
&lt;li&gt;DELETE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MySQL only sees SQL.&lt;/p&gt;

&lt;p&gt;So from the database side, you usually filter write operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSERT
UPDATE
DELETE
COMMIT
ROLLBACK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, a POST request that creates a user usually results in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A PATCH request may result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A delete action may result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So instead of searching for “POST” inside MySQL, search for the SQL operation caused by that POST request.&lt;/p&gt;




&lt;h2&gt;
  
  
  Application-Level Request Tracking Example
&lt;/h2&gt;

&lt;p&gt;If you want to connect application request logs with MySQL logs, add a request ID at application level.&lt;/p&gt;

&lt;p&gt;Laravel example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$requestId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'X-Request-Id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;withContext&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'request_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$requestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'method'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="s1"&gt;'path'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Request started'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your Laravel logs can tell you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;request_id: 7e71e1d8-3d9b-45e5-8a80-ef98c0d9c101
method: POST
path: /users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can add a temporary MySQL session marker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SET @debug_request_id = ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$requestId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This statement will also appear inside the General Query Log.&lt;/p&gt;

&lt;p&gt;Now search for that marker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%debug_request_id%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you find the &lt;code&gt;thread_id&lt;/code&gt;, inspect all queries from that same thread:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;thread_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you a bridge between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laravel request&lt;/li&gt;
&lt;li&gt;controller/service logs&lt;/li&gt;
&lt;li&gt;actual MySQL queries&lt;/li&gt;
&lt;li&gt;transaction commit/rollback result&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is much better than guessing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example: Debugging a Failed User Creation
&lt;/h2&gt;

&lt;p&gt;Imagine this flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user submits form&lt;/li&gt;
&lt;li&gt;Laravel receives POST request&lt;/li&gt;
&lt;li&gt;application starts transaction&lt;/li&gt;
&lt;li&gt;user is inserted&lt;/li&gt;
&lt;li&gt;campaign is assigned&lt;/li&gt;
&lt;li&gt;lead is generated&lt;/li&gt;
&lt;li&gt;something fails&lt;/li&gt;
&lt;li&gt;transaction rolls back&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From application logs, you may only see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User creation failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But from MySQL general log, you can check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%users%'&lt;/span&gt;
   &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%campaigns%'&lt;/span&gt;
   &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%leads%'&lt;/span&gt;
   &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'commit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rollback'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you may discover:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;campaigns&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;leads&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;ROLLBACK&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the problem is clear.&lt;/p&gt;

&lt;p&gt;The user insert happened.&lt;/p&gt;

&lt;p&gt;The campaign update happened.&lt;/p&gt;

&lt;p&gt;The lead insert happened.&lt;/p&gt;

&lt;p&gt;But the transaction rolled back.&lt;/p&gt;

&lt;p&gt;So the debugging direction changes immediately.&lt;/p&gt;

&lt;p&gt;You stop asking:&lt;/p&gt;

&lt;p&gt;“Why did user insert fail?”&lt;/p&gt;

&lt;p&gt;And start asking:&lt;/p&gt;

&lt;p&gt;“What caused the rollback?”&lt;/p&gt;

&lt;p&gt;That is a huge difference.&lt;/p&gt;




&lt;h2&gt;
  
  
  Clean General Log Table
&lt;/h2&gt;

&lt;p&gt;Do not let &lt;code&gt;mysql.general_log&lt;/code&gt; grow forever.&lt;/p&gt;

&lt;p&gt;After debugging, clean it.&lt;/p&gt;

&lt;p&gt;First, disable General Query Log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'OFF'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then truncate the table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;TRUNCATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you still need debugging, enable it again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full cleanup flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'OFF'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;TRUNCATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important note:&lt;/p&gt;

&lt;p&gt;Do not use this as permanent production logging.&lt;/p&gt;

&lt;p&gt;This is for temporary debugging.&lt;/p&gt;




&lt;h2&gt;
  
  
  Disable General Query Log After Debugging
&lt;/h2&gt;

&lt;p&gt;This is the part developers often forget.&lt;/p&gt;

&lt;p&gt;After investigation, turn it off:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'OFF'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;VARIABLES&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'general_log'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the value is &lt;code&gt;OFF&lt;/code&gt;, logging is disabled.&lt;/p&gt;




&lt;h2&gt;
  
  
  One Important Thing Most Developers Ignore
&lt;/h2&gt;

&lt;p&gt;Do not leave &lt;code&gt;general_log&lt;/code&gt; permanently enabled in production.&lt;/p&gt;

&lt;p&gt;That is a bad idea.&lt;/p&gt;

&lt;p&gt;Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;logs become massive&lt;/li&gt;
&lt;li&gt;storage grows quickly&lt;/li&gt;
&lt;li&gt;performance can suffer&lt;/li&gt;
&lt;li&gt;sensitive query data may appear in logs&lt;/li&gt;
&lt;li&gt;debugging tables can become noisy very fast&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The smarter workflow is temporary debugging.&lt;/p&gt;




&lt;h2&gt;
  
  
  Temporary Debugging Workflow
&lt;/h2&gt;

&lt;p&gt;Enable table logging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;log_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'TABLE'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reproduce the issue.&lt;/p&gt;

&lt;p&gt;Check recent queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Filter by table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%users%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Filter by transaction result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'commit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rollback'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trace one thread:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;argument&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;thread_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;ASC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then disable logging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'OFF'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And clean the table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;TRUNCATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the workflow.&lt;/p&gt;

&lt;p&gt;Enable.&lt;/p&gt;

&lt;p&gt;Reproduce.&lt;/p&gt;

&lt;p&gt;Inspect.&lt;/p&gt;

&lt;p&gt;Filter.&lt;/p&gt;

&lt;p&gt;Understand.&lt;/p&gt;

&lt;p&gt;Disable.&lt;/p&gt;

&lt;p&gt;Clean.&lt;/p&gt;

&lt;p&gt;That is how you stop guessing and start debugging from the place that sees everything:&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>debugging</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Stack Pointer vs Base Pointer: A Friendly Guide to How Function Calls Work</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Mon, 18 May 2026 11:38:49 +0000</pubDate>
      <link>https://dev.to/tahsin000/stack-pointer-vs-base-pointer-a-friendly-guide-to-how-function-calls-work-35nc</link>
      <guid>https://dev.to/tahsin000/stack-pointer-vs-base-pointer-a-friendly-guide-to-how-function-calls-work-35nc</guid>
      <description>&lt;p&gt;Have you ever called a function and wondered what really happens inside the computer?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We know the output will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But inside the machine, a lot of quiet work happens.&lt;/p&gt;

&lt;p&gt;The CPU needs to remember:&lt;/p&gt;

&lt;p&gt;Where did this function start?&lt;/p&gt;

&lt;p&gt;Where should it return?&lt;/p&gt;

&lt;p&gt;Where are the arguments?&lt;/p&gt;

&lt;p&gt;Where are the local variables?&lt;/p&gt;

&lt;p&gt;Which function is currently running?&lt;/p&gt;

&lt;p&gt;This is where the &lt;strong&gt;stack&lt;/strong&gt;, &lt;strong&gt;stack frame&lt;/strong&gt;, &lt;strong&gt;stack pointer&lt;/strong&gt;, and &lt;strong&gt;base pointer&lt;/strong&gt; come in.&lt;/p&gt;

&lt;p&gt;Let’s break them down in a simple way.&lt;/p&gt;




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

&lt;h2&gt;
  
  
  First, What Is a Stack?
&lt;/h2&gt;

&lt;p&gt;A stack is a special area of memory used while a program is running.&lt;/p&gt;

&lt;p&gt;Think of it like a stack of plates.&lt;/p&gt;

&lt;p&gt;You put a plate on top.&lt;/p&gt;

&lt;p&gt;You remove the top plate first.&lt;/p&gt;

&lt;p&gt;You cannot remove a plate from the middle without disturbing the others.&lt;/p&gt;

&lt;p&gt;In programming, the stack works in a similar way.&lt;/p&gt;

&lt;p&gt;When a function is called, the program creates a small memory area for that function. This small area is called a &lt;strong&gt;stack frame&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When the function finishes, its stack frame is removed.&lt;/p&gt;

&lt;p&gt;So if &lt;code&gt;main()&lt;/code&gt; calls &lt;code&gt;add()&lt;/code&gt;, the stack may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add() stack frame
main() stack frame
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;add()&lt;/code&gt; is on top because it is currently running.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;add()&lt;/code&gt; finishes, its stack frame is removed, and the program returns to &lt;code&gt;main()&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Stack Frame?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;stack frame&lt;/strong&gt; is the memory space a function gets while it is running.&lt;/p&gt;

&lt;p&gt;It usually stores things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Function arguments
Return address
Old base pointer
Local variables
Temporary values
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our &lt;code&gt;add()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stack frame may contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x = 10
y = 4
return address
old base pointer
result = 14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact layout depends on the CPU, compiler, operating system, and calling convention. But the main idea is the same:&lt;/p&gt;

&lt;p&gt;A function needs a private workspace while it runs.&lt;/p&gt;

&lt;p&gt;That workspace is its stack frame.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Quick Note About Memory Addresses
&lt;/h2&gt;

&lt;p&gt;Before we go deeper, let’s clear up one common confusion.&lt;/p&gt;

&lt;p&gt;On most modern systems, memory is &lt;strong&gt;byte-addressable&lt;/strong&gt;. That means every byte has its own address.&lt;/p&gt;

&lt;p&gt;So memory addresses can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0, 1, 2, 3, 4, 5, 6, 7, 8 ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But when we draw memory in larger chunks, like 4-byte chunks on a 32-bit-style example, we often label them like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0, 4, 8, 12, 16 ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does &lt;strong&gt;not&lt;/strong&gt; mean addresses &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, and &lt;code&gt;3&lt;/code&gt; do not exist.&lt;/p&gt;

&lt;p&gt;It simply means we are drawing memory in 4-byte blocks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Address 0  -&amp;gt; byte 1 of first block
Address 1  -&amp;gt; byte 2 of first block
Address 2  -&amp;gt; byte 3 of first block
Address 3  -&amp;gt; byte 4 of first block

Address 4  -&amp;gt; byte 1 of second block
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this article, we will use a simple 32-bit mental model where each slot is 4 bytes.&lt;/p&gt;

&lt;p&gt;So our stack addresses may move like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;80
76
72
68
64
60
56
52
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In many systems, the stack grows downward, which means the address gets smaller as new data is pushed onto the stack.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is the Stack Pointer?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;stack pointer&lt;/strong&gt;, often called &lt;code&gt;SP&lt;/code&gt;, points to the current top of the stack.&lt;/p&gt;

&lt;p&gt;Imagine you are stacking plates.&lt;/p&gt;

&lt;p&gt;The stack pointer is like your finger pointing at the top plate.&lt;/p&gt;

&lt;p&gt;When a new value is pushed onto the stack, the stack pointer moves.&lt;/p&gt;

&lt;p&gt;When a value is popped from the stack, the stack pointer moves back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before push:

Address 76 -&amp;gt; old value
Address 72 -&amp;gt; top of stack  &amp;lt;- SP

Push new value:

Address 76 -&amp;gt; old value
Address 72 -&amp;gt; old top
Address 68 -&amp;gt; new value     &amp;lt;- SP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because our example stack grows downward, pushing data makes &lt;code&gt;SP&lt;/code&gt; move from &lt;code&gt;72&lt;/code&gt; to &lt;code&gt;68&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So the stack pointer is dynamic.&lt;/p&gt;

&lt;p&gt;It keeps changing as the stack grows and shrinks.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is the Base Pointer?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;base pointer&lt;/strong&gt;, often called &lt;code&gt;BP&lt;/code&gt; or frame pointer, points to a stable location inside the current function’s stack frame.&lt;/p&gt;

&lt;p&gt;Unlike the stack pointer, the base pointer usually stays fixed while the function is running.&lt;/p&gt;

&lt;p&gt;Why do we need that?&lt;/p&gt;

&lt;p&gt;Because the stack pointer keeps moving.&lt;/p&gt;

&lt;p&gt;If the program only used &lt;code&gt;SP&lt;/code&gt;, it would be hard to find local variables and arguments after more values are pushed or popped.&lt;/p&gt;

&lt;p&gt;The base pointer solves this problem.&lt;/p&gt;

&lt;p&gt;It gives the function a fixed reference point.&lt;/p&gt;

&lt;p&gt;From that fixed point, the program can find values using offsets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BP + 8   -&amp;gt; first argument
BP + 12  -&amp;gt; second argument
BP - 4   -&amp;gt; first local variable
BP - 8   -&amp;gt; second local variable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the base pointer helps the program answer questions like:&lt;/p&gt;

&lt;p&gt;Where is &lt;code&gt;x&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Where is &lt;code&gt;y&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Where is &lt;code&gt;result&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Where should I return after this function ends?&lt;/p&gt;




&lt;h2&gt;
  
  
  Stack Pointer vs Base Pointer
&lt;/h2&gt;

&lt;p&gt;Here is the simple difference:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Register&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stack Pointer&lt;/td&gt;
&lt;td&gt;Points to the current top of the stack&lt;/td&gt;
&lt;td&gt;Changes often&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Base Pointer&lt;/td&gt;
&lt;td&gt;Points to a fixed place in the current stack frame&lt;/td&gt;
&lt;td&gt;Usually stays fixed during the function&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A simple way to remember it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SP&lt;/code&gt; tracks movement.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;BP&lt;/code&gt; gives stability.&lt;/p&gt;

&lt;p&gt;The stack pointer is like a moving bookmark.&lt;/p&gt;

&lt;p&gt;The base pointer is like an anchor.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens When &lt;code&gt;main()&lt;/code&gt; Runs?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;main()&lt;/code&gt; starts, the program creates a stack frame for &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside that frame, it stores local variables such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a = 10
sum = ?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, &lt;code&gt;sum&lt;/code&gt; does not have its final value because &lt;code&gt;add(a, 4)&lt;/code&gt; has not returned yet.&lt;/p&gt;

&lt;p&gt;So the stack may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main stack frame
----------------
return address
old BP
a = 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;main()&lt;/code&gt; calls &lt;code&gt;add(a, 4)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That means the program needs a new stack frame for &lt;code&gt;add()&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens When &lt;code&gt;add()&lt;/code&gt; Is Called?
&lt;/h2&gt;

&lt;p&gt;This line is important:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The program needs to call &lt;code&gt;add()&lt;/code&gt; with two values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x = 10
y = 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So it creates a new stack frame for &lt;code&gt;add()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A simplified stack frame may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add stack frame
---------------
y = 4
x = 10
return address
old BP
result = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The order can vary depending on the system, but the idea is the same.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;add()&lt;/code&gt; function needs:&lt;/p&gt;

&lt;p&gt;Its arguments: &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A return address: where to go back after &lt;code&gt;add()&lt;/code&gt; finishes&lt;/p&gt;

&lt;p&gt;The old base pointer: so the caller’s stack frame can be restored&lt;/p&gt;

&lt;p&gt;Its local variable: &lt;code&gt;result&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Do We Need a Return Address?
&lt;/h2&gt;

&lt;p&gt;When &lt;code&gt;main()&lt;/code&gt; calls &lt;code&gt;add()&lt;/code&gt;, the CPU jumps to the code for &lt;code&gt;add()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But after &lt;code&gt;add()&lt;/code&gt; finishes, the CPU must know where to go back.&lt;/p&gt;

&lt;p&gt;It needs to return to this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More specifically, it needs to return to the next step after the function call, so the returned value can be stored in &lt;code&gt;sum&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That “go back here” location is called the &lt;strong&gt;return address&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Without a return address, the program would get lost.&lt;/p&gt;

&lt;p&gt;It would finish &lt;code&gt;add()&lt;/code&gt; and then have no idea where to continue.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Save the Old Base Pointer?
&lt;/h2&gt;

&lt;p&gt;Before &lt;code&gt;add()&lt;/code&gt; starts, &lt;code&gt;main()&lt;/code&gt; already has its own base pointer.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;add()&lt;/code&gt; starts, it gets a new base pointer for its own stack frame.&lt;/p&gt;

&lt;p&gt;But when &lt;code&gt;add()&lt;/code&gt; finishes, the program must restore the old base pointer so &lt;code&gt;main()&lt;/code&gt; can continue correctly.&lt;/p&gt;

&lt;p&gt;That is why the old base pointer is saved inside the new stack frame.&lt;/p&gt;

&lt;p&gt;Think of it like leaving a breadcrumb.&lt;/p&gt;

&lt;p&gt;Before entering a new function, the program says:&lt;/p&gt;

&lt;p&gt;“Let me save where I came from, so I can restore it later.”&lt;/p&gt;

&lt;p&gt;When the function ends, the old base pointer is loaded back.&lt;/p&gt;

&lt;p&gt;Now the caller’s stack frame becomes active again.&lt;/p&gt;




&lt;h2&gt;
  
  
  How &lt;code&gt;add()&lt;/code&gt; Finds &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, and &lt;code&gt;result&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Inside &lt;code&gt;add()&lt;/code&gt;, we have this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CPU does not understand variable names like humans do.&lt;/p&gt;

&lt;p&gt;It does not think:&lt;/p&gt;

&lt;p&gt;“Oh, &lt;code&gt;x&lt;/code&gt; means 10 and &lt;code&gt;y&lt;/code&gt; means 4.”&lt;/p&gt;

&lt;p&gt;Instead, the compiler maps variables to memory locations.&lt;/p&gt;

&lt;p&gt;Using the base pointer, the program can find values by offsets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BP + 8   -&amp;gt; x
BP + 12  -&amp;gt; y
BP - 4   -&amp;gt; result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So when the function needs &lt;code&gt;x&lt;/code&gt;, it looks at something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BP + 8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it needs &lt;code&gt;y&lt;/code&gt;, it looks at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BP + 12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it needs to store &lt;code&gt;result&lt;/code&gt;, it may use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BP - 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;becomes something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;read value at BP + 8
read value at BP + 12
add them
store the answer at BP - 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x = 10
y = 4

result = 14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Returning Back to &lt;code&gt;main()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Now &lt;code&gt;add()&lt;/code&gt; reaches this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function returns &lt;code&gt;14&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then the &lt;code&gt;add()&lt;/code&gt; stack frame is no longer needed.&lt;/p&gt;

&lt;p&gt;So the program removes it from the stack.&lt;/p&gt;

&lt;p&gt;The stack pointer moves back.&lt;/p&gt;

&lt;p&gt;The old base pointer is restored.&lt;/p&gt;

&lt;p&gt;The return address tells the CPU where to continue.&lt;/p&gt;

&lt;p&gt;Now we are back inside &lt;code&gt;main()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The returned value &lt;code&gt;14&lt;/code&gt; is stored in &lt;code&gt;sum&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;14&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then this line runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  A Simple Visual Summary
&lt;/h2&gt;

&lt;p&gt;Here is a simplified version of what happens.&lt;/p&gt;

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

&lt;p&gt;Before calling &lt;code&gt;add()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main stack frame
----------------
a = 10
sum = ?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While &lt;code&gt;add()&lt;/code&gt; is running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add stack frame
---------------
x = 10
y = 4
result = 14

main stack frame
----------------
a = 10
sum = ?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After &lt;code&gt;add()&lt;/code&gt; returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main stack frame
----------------
a = 10
sum = 14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;main()&lt;/code&gt; prints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Does This Always Work Exactly Like This?
&lt;/h2&gt;

&lt;p&gt;Not always.&lt;/p&gt;

&lt;p&gt;This article uses a simplified model to make the concept easy to understand.&lt;/p&gt;

&lt;p&gt;Real systems can be more complex.&lt;/p&gt;

&lt;p&gt;Modern compilers may optimize away the base pointer.&lt;/p&gt;

&lt;p&gt;Function arguments may be passed through registers instead of the stack.&lt;/p&gt;

&lt;p&gt;Go uses goroutine stacks, which can grow and move.&lt;/p&gt;

&lt;p&gt;The exact stack layout depends on architecture, compiler version, and calling convention.&lt;/p&gt;

&lt;p&gt;But the core idea is still useful:&lt;/p&gt;

&lt;p&gt;Functions need stack frames.&lt;/p&gt;

&lt;p&gt;The stack pointer tracks the top of the stack.&lt;/p&gt;

&lt;p&gt;The base pointer gives a stable reference point inside a function frame.&lt;/p&gt;

&lt;p&gt;Return addresses help the program continue from the correct place.&lt;/p&gt;

&lt;p&gt;Old base pointers help restore the caller’s frame.&lt;/p&gt;

&lt;p&gt;Once you understand this model, debugging, assembly, recursion, memory layout, and low-level programming all become much less mysterious.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Real-Life Way to Remember It
&lt;/h2&gt;

&lt;p&gt;Imagine you are reading a book and solving exercises.&lt;/p&gt;

&lt;p&gt;You are on Chapter 5.&lt;/p&gt;

&lt;p&gt;Suddenly, Chapter 5 says:&lt;/p&gt;

&lt;p&gt;“Before continuing, go solve Example 2 from Chapter 3.”&lt;/p&gt;

&lt;p&gt;So you place a bookmark in Chapter 5.&lt;/p&gt;

&lt;p&gt;Then you go to Chapter 3 and solve the example.&lt;/p&gt;

&lt;p&gt;After finishing, you return to the bookmark in Chapter 5.&lt;/p&gt;

&lt;p&gt;In this story:&lt;/p&gt;

&lt;p&gt;The bookmark is like the return address.&lt;/p&gt;

&lt;p&gt;Your current page position is like the stack pointer.&lt;/p&gt;

&lt;p&gt;The start of your current exercise notes is like the base pointer.&lt;/p&gt;

&lt;p&gt;The notes for each exercise are like stack frames.&lt;/p&gt;

&lt;p&gt;Every function call is like temporarily jumping into another task, while carefully remembering how to come back.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>computerscience</category>
      <category>go</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to Connect a Namecheap Domain to a DigitalOcean Droplet with Nginx</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Sat, 16 May 2026 15:31:38 +0000</pubDate>
      <link>https://dev.to/tahsin000/how-to-connect-a-namecheap-domain-to-a-digitalocean-droplet-with-nginx-2mok</link>
      <guid>https://dev.to/tahsin000/how-to-connect-a-namecheap-domain-to-a-digitalocean-droplet-with-nginx-2mok</guid>
      <description>&lt;p&gt;Buying a domain is exciting. Creating a server is exciting too.&lt;/p&gt;

&lt;p&gt;But the moment you try to connect both of them, things can feel confusing.&lt;/p&gt;

&lt;p&gt;You bought your domain from &lt;strong&gt;Namecheap&lt;/strong&gt;. You created a VPS on &lt;strong&gt;DigitalOcean&lt;/strong&gt;. Now you expect your website to open when someone visits your domain.&lt;/p&gt;

&lt;p&gt;But unlike shared hosting or cPanel hosting, DigitalOcean does not automatically connect everything for you.&lt;/p&gt;

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

&lt;p&gt;You need to set up two important things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;DNS&lt;/strong&gt; : so your domain points to your server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nginx&lt;/strong&gt; : so your server knows how to serve your website&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this guide, we will walk through the full setup in a simple and beginner-friendly way.&lt;/p&gt;

&lt;p&gt;By the end, your domain will point to your DigitalOcean Droplet, Nginx will serve your website, and HTTPS will be enabled.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Big Picture
&lt;/h2&gt;

&lt;p&gt;Before touching any settings, let’s understand the flow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Namecheap Domain
        ↓
DNS points to DigitalOcean IP
        ↓
DigitalOcean Droplet
        ↓
Nginx Web Server
        ↓
Your Website
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your domain is like a human-friendly address.&lt;/p&gt;

&lt;p&gt;Your DigitalOcean Droplet is the actual server.&lt;/p&gt;

&lt;p&gt;DNS connects the domain to the server.&lt;/p&gt;

&lt;p&gt;Nginx receives the request and serves your website files or forwards traffic to your app.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Create a DigitalOcean Droplet
&lt;/h2&gt;

&lt;p&gt;First, create a Droplet on DigitalOcean.&lt;/p&gt;

&lt;p&gt;For a beginner project or test website, this setup is usually enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ubuntu 22.04 LTS
Basic Droplet
1 GB RAM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the Droplet is created, DigitalOcean will give you a public IP address.&lt;/p&gt;

&lt;p&gt;It will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;159.89.xxx.xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep this IP address safe. You will need it in the next step.&lt;/p&gt;

&lt;p&gt;This IP is where your domain will point.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Point Your Namecheap Domain to DigitalOcean
&lt;/h2&gt;

&lt;p&gt;Now go to your Namecheap account.&lt;/p&gt;

&lt;p&gt;Open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Domain List
→ Manage
→ Advanced DNS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two common ways to connect your domain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Option A: Use A Records
&lt;/h2&gt;

&lt;p&gt;This is the easiest method for beginners.&lt;/p&gt;

&lt;p&gt;Add these DNS records:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Host&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A Record&lt;/td&gt;
&lt;td&gt;@&lt;/td&gt;
&lt;td&gt;Your DigitalOcean IP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A Record&lt;/td&gt;
&lt;td&gt;www&lt;/td&gt;
&lt;td&gt;Your DigitalOcean IP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Host&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A Record&lt;/td&gt;
&lt;td&gt;@&lt;/td&gt;
&lt;td&gt;159.89.xxx.xxx&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A Record&lt;/td&gt;
&lt;td&gt;www&lt;/td&gt;
&lt;td&gt;159.89.xxx.xxx&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can keep TTL as the default value.&lt;/p&gt;

&lt;p&gt;Here is what this does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com       → DigitalOcean server
www.example.com   → DigitalOcean server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So both the root domain and the &lt;code&gt;www&lt;/code&gt; version will go to the same Droplet.&lt;/p&gt;

&lt;p&gt;For most simple projects, this is the best starting point.&lt;/p&gt;




&lt;h2&gt;
  
  
  Option B: Use DigitalOcean Nameservers
&lt;/h2&gt;

&lt;p&gt;Another option is to manage DNS from DigitalOcean instead of Namecheap.&lt;/p&gt;

&lt;p&gt;In DigitalOcean, go to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Networking
→ Domains
→ Add Domain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add your domain there.&lt;/p&gt;

&lt;p&gt;DigitalOcean will give you nameservers like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ns1.digitalocean.com
ns2.digitalocean.com
ns3.digitalocean.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then go back to Namecheap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Domain
→ Manage
→ Nameservers
→ Custom DNS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add those three DigitalOcean nameservers and save.&lt;/p&gt;

&lt;p&gt;This method is useful when you want to manage all DNS records from DigitalOcean, especially if you have multiple subdomains or services.&lt;/p&gt;




&lt;h2&gt;
  
  
  Which DNS Method Should You Choose?
&lt;/h2&gt;

&lt;p&gt;For beginners, use &lt;strong&gt;A Records&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is simple, clear, and easy to debug.&lt;/p&gt;

&lt;p&gt;Use DigitalOcean nameservers when your setup becomes larger, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;api.example.com
app.example.com
blog.example.com
admin.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For now, we will continue with the beginner-friendly A Record method.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Wait for DNS Propagation
&lt;/h2&gt;

&lt;p&gt;DNS changes are not always instant.&lt;/p&gt;

&lt;p&gt;Sometimes they work in a few minutes. Sometimes they take longer.&lt;/p&gt;

&lt;p&gt;Usually, it can take:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5 minutes to 1 hour
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In some cases, it may take up to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;24 hours
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use tools like DNS Checker to see whether your domain is pointing to the correct server IP.&lt;/p&gt;

&lt;p&gt;A common beginner mistake is changing DNS and immediately thinking something is broken. Sometimes nothing is broken. DNS just needs a little time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Connect to Your Server with SSH
&lt;/h2&gt;

&lt;p&gt;Now connect to your DigitalOcean Droplet.&lt;/p&gt;

&lt;p&gt;On Mac or Linux, open your terminal.&lt;/p&gt;

&lt;p&gt;On Windows, you can use PowerShell or PuTTY.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@YOUR_SERVER_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@159.89.xxx.xxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first time you connect, your terminal may ask for confirmation. Type:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then enter your password or use your SSH key, depending on how you created the Droplet.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Install Nginx
&lt;/h2&gt;

&lt;p&gt;Once you are inside the server, update the package list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then install Nginx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check if Nginx is running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is working, you should see that Nginx is active.&lt;/p&gt;

&lt;p&gt;At this point, if you open your server IP in the browser, you may see the default Nginx welcome page.&lt;/p&gt;

&lt;p&gt;That means your web server is working.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Configure the Firewall
&lt;/h2&gt;

&lt;p&gt;Ubuntu servers often use &lt;code&gt;ufw&lt;/code&gt; for firewall management.&lt;/p&gt;

&lt;p&gt;Allow Nginx traffic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow &lt;span class="s1"&gt;'Nginx Full'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also allow SSH so you do not lock yourself out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow OpenSSH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then enable the firewall:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check the firewall status with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see that HTTP, HTTPS, and SSH traffic are allowed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Create a Website Folder
&lt;/h2&gt;

&lt;p&gt;Now create a folder for your website.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/myproject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a test HTML file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /var/www/myproject/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello from DigitalOcean&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CTRL + X
Y
Enter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple file will help us confirm that the domain and Nginx setup are working.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 8: Create an Nginx Server Block
&lt;/h2&gt;

&lt;p&gt;An Nginx server block tells Nginx how to handle traffic for a specific domain.&lt;/p&gt;

&lt;p&gt;Create a new config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/nginx/sites-available/myproject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste this configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/myproject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;example.com&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With your real domain.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;mycoolsite.com&lt;/span&gt; &lt;span class="s"&gt;www.mycoolsite.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This config says:&lt;/p&gt;

&lt;p&gt;“When someone visits this domain, serve files from &lt;code&gt;/var/www/myproject&lt;/code&gt;.”&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 9: Enable the Site
&lt;/h2&gt;

&lt;p&gt;Nginx keeps available site configs in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/nginx/sites-available/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it only uses configs that are linked in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/nginx/sites-enabled/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we need to enable the site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 10: Test and Reload Nginx
&lt;/h2&gt;

&lt;p&gt;Before restarting Nginx, always test the config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is fine, you should see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;syntax is ok
test is successful
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now reload Nginx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open your domain in the browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello from DigitalOcean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great. Your domain is now connected to your Droplet.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 11: Add HTTPS with Certbot
&lt;/h2&gt;

&lt;p&gt;A production website should use HTTPS.&lt;/p&gt;

&lt;p&gt;For that, we can use Certbot with Let’s Encrypt.&lt;/p&gt;

&lt;p&gt;Install Certbot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Certbot will ask you to choose the domain.&lt;/p&gt;

&lt;p&gt;Select your domain and allow redirect to HTTPS.&lt;/p&gt;

&lt;p&gt;After that, your site should work with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Certbot also sets up automatic renewal, so your SSL certificate can renew before it expires.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Architecture
&lt;/h2&gt;

&lt;p&gt;Your setup now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Namecheap
   ↓
DNS A Record
   ↓
DigitalOcean Droplet IP
   ↓
Nginx
   ↓
Website Files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a common real-world setup used by many developers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Feels Different from cPanel Hosting
&lt;/h2&gt;

&lt;p&gt;If you are coming from cPanel hosting, DigitalOcean may feel harder at first.&lt;/p&gt;

&lt;p&gt;That is normal.&lt;/p&gt;

&lt;p&gt;With cPanel hosting, the hosting company usually handles many things for you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DNS
Apache or Nginx
SSL
PHP
File manager
Email tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You often just change nameservers and upload your files.&lt;/p&gt;

&lt;p&gt;But with a DigitalOcean VPS, you manage the server yourself.&lt;/p&gt;

&lt;p&gt;That means you are responsible for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nginx
Firewall
SSL
App runtime
Deployment
Security
Logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The benefit is flexibility.&lt;/p&gt;

&lt;p&gt;You can run Node.js, Laravel, Docker, PostgreSQL, Redis, background workers, multiple apps, and more.&lt;/p&gt;

&lt;p&gt;The tradeoff is that you need to understand the server setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Real-Life Example
&lt;/h2&gt;

&lt;p&gt;Imagine you built a small portfolio website.&lt;/p&gt;

&lt;p&gt;You bought:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myportfolio.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;from Namecheap.&lt;/p&gt;

&lt;p&gt;Then you created a DigitalOcean Droplet with this IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;159.89.100.50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Namecheap, you add:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Host&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A Record&lt;/td&gt;
&lt;td&gt;@&lt;/td&gt;
&lt;td&gt;159.89.100.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A Record&lt;/td&gt;
&lt;td&gt;www&lt;/td&gt;
&lt;td&gt;159.89.100.50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Then on your server, your Nginx config looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;myportfolio.com&lt;/span&gt; &lt;span class="s"&gt;www.myportfolio.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/myportfolio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After reloading Nginx and setting up SSL, visitors can open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://myportfolio.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And see your website.&lt;/p&gt;

&lt;p&gt;That is the full journey from domain to live website.&lt;/p&gt;

</description>
      <category>nginx</category>
      <category>dohackathon</category>
      <category>dns</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Hubs, Switches, and Routers Explained Like You're Debugging a Real Network</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Mon, 11 May 2026 06:48:03 +0000</pubDate>
      <link>https://dev.to/tahsin000/hubs-switches-and-routers-explained-like-youre-debugging-a-real-network-4co5</link>
      <guid>https://dev.to/tahsin000/hubs-switches-and-routers-explained-like-youre-debugging-a-real-network-4co5</guid>
      <description>&lt;p&gt;Have you ever connected your laptop to Wi-Fi, opened a browser, typed a URL, and wondered:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How does my message actually reach the right computer?"&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;As developers, we often work with APIs, servers, ports, IP addresses, localhost, Docker networks, cloud servers, and routers. But networking can feel confusing because many explanations jump straight into heavy terms.&lt;/p&gt;

&lt;p&gt;So let's slow down and make it simple.&lt;/p&gt;

&lt;p&gt;In this post, we'll understand three important network devices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hub&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Switch&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Router&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll also see how data moves from one computer to another inside a local network, and how your computer decides whether to send data directly to another device or through the router.&lt;/p&gt;

&lt;p&gt;This article is based on the provided networking class transcript about hubs, switches, routers, MAC tables, and internal communication. &lt;/p&gt;




&lt;h2&gt;
  
  
  First, Imagine a Small Room Full of Computers
&lt;/h2&gt;

&lt;p&gt;Imagine five computers connected in the same room.&lt;/p&gt;

&lt;p&gt;One computer wants to send a message to another computer.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Computer A wants to send data to Computer D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That sounds simple. But the network has to answer some important questions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Who sent the data?
Who should receive it?
Are both devices in the same network?
Should the data go to another device first?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where hubs, switches, and routers come in.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hub: The Loud but Not-So-Smart Device
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;hub&lt;/strong&gt; is one of the simplest network devices.&lt;/p&gt;

&lt;p&gt;You can think of it like a loudspeaker.&lt;/p&gt;

&lt;p&gt;When one computer sends data to a hub, the hub does not check who the data is for. It simply forwards the data to every other connected port.&lt;/p&gt;

&lt;p&gt;So if Computer A sends data through a hub, the hub sends it to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Computer B
Computer C
Computer D
Computer E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if the message was only meant for Computer D.&lt;/p&gt;

&lt;p&gt;The other computers receive the data, check it, and then ignore it if it is not meant for them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is a hub considered "not smart"?
&lt;/h3&gt;

&lt;p&gt;Because a hub works at the &lt;strong&gt;physical layer&lt;/strong&gt;, also called &lt;strong&gt;Layer 1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It only understands electrical signals or bits.&lt;/p&gt;

&lt;p&gt;It does not understand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC addresses
IP addresses
Ports
Applications
Actual message content
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So a hub cannot make smart forwarding decisions.&lt;/p&gt;

&lt;p&gt;It just repeats the signal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple way to remember a hub
&lt;/h3&gt;

&lt;p&gt;A hub says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I don't know who needs this, so I'll send it to everyone."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is why hubs are rarely used in modern networks.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Switch: A Smarter Device That Learns
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;switch&lt;/strong&gt; is much smarter than a hub.&lt;/p&gt;

&lt;p&gt;A switch works at the &lt;strong&gt;data link layer&lt;/strong&gt;, also called &lt;strong&gt;Layer 2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That means a switch can understand &lt;strong&gt;MAC addresses&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A MAC address is like the hardware address of a network device. Every network interface has one.&lt;/p&gt;

&lt;p&gt;For example, imagine five devices connected to a switch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Port 1 -&amp;gt; Computer A
Port 2 -&amp;gt; Computer B
Port 3 -&amp;gt; Computer C
Port 4 -&amp;gt; Computer D
Port 5 -&amp;gt; Computer E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each computer has a MAC address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Computer A -&amp;gt; MAC A
Computer B -&amp;gt; MAC B
Computer C -&amp;gt; MAC C
Computer D -&amp;gt; MAC D
Computer E -&amp;gt; MAC E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Computer A wants to send data to Computer D.&lt;/p&gt;

&lt;p&gt;The Ethernet frame may look like this in a simplified way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source MAC: A
Destination MAC: D
Data: Hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the switch receives this frame, it checks the &lt;strong&gt;source MAC address&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC A came from Port 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it saves that information in a table.&lt;/p&gt;

&lt;p&gt;This table is commonly called:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC address table
CAM table
Forwarding database
Bridge table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Different books and vendors may use different names, but the idea is the same.&lt;/p&gt;

&lt;p&gt;The switch keeps a record like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC Address    Port
A              1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Happens When the Switch Does Not Know the Destination?
&lt;/h2&gt;

&lt;p&gt;Now the switch checks the destination MAC address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destination MAC: D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But imagine this is the first time the switch has seen Computer D.&lt;/p&gt;

&lt;p&gt;So the switch does not yet know which port leads to MAC D.&lt;/p&gt;

&lt;p&gt;What does it do?&lt;/p&gt;

&lt;p&gt;It &lt;strong&gt;floods&lt;/strong&gt; the frame.&lt;/p&gt;

&lt;p&gt;That means it sends the frame to every port except the port it came from.&lt;/p&gt;

&lt;p&gt;So the frame goes to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Port 2
Port 3
Port 4
Port 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Computer B receives it and says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This is not for me.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Computer C says the same.&lt;/p&gt;

&lt;p&gt;Computer E says the same.&lt;/p&gt;

&lt;p&gt;But Computer D checks the destination MAC and says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This is mine.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So Computer D accepts the frame.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the Switch Learns Over Time
&lt;/h2&gt;

&lt;p&gt;Now Computer D replies to Computer A.&lt;/p&gt;

&lt;p&gt;The reply frame looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source MAC: D
Destination MAC: A
Data: Hello back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The switch receives the frame from Port 4.&lt;/p&gt;

&lt;p&gt;It checks the source MAC address and learns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC D came from Port 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the switch table becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC Address    Port
A              1
D              4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next time Computer A sends data to Computer D, the switch does not need to flood the frame.&lt;/p&gt;

&lt;p&gt;It already knows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC D is on Port 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So it sends the frame only to Port 4.&lt;/p&gt;

&lt;p&gt;That is why a switch is more efficient than a hub.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple way to remember a switch
&lt;/h3&gt;

&lt;p&gt;A switch says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I’ll learn where devices are, then send data only where it needs to go."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Hub vs Switch in One Simple Example
&lt;/h2&gt;

&lt;p&gt;Imagine a classroom.&lt;/p&gt;

&lt;p&gt;A hub is like a student who receives a note and shouts it to the whole class.&lt;/p&gt;

&lt;p&gt;A switch is like a helpful class monitor who learns where everyone sits and quietly gives the note to the right person.&lt;/p&gt;

&lt;p&gt;That is the main difference.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Does the Router Fit In?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;router&lt;/strong&gt; works at the &lt;strong&gt;network layer&lt;/strong&gt;, also called &lt;strong&gt;Layer 3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That means a router understands &lt;strong&gt;IP addresses&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A switch mainly cares about MAC addresses inside a local network.&lt;/p&gt;

&lt;p&gt;A router cares about moving data between different networks.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your laptop -&amp;gt; your home network
Your home network -&amp;gt; the internet
The internet -&amp;gt; another server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The router is the device that connects your local network to other networks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple way to remember a router
&lt;/h3&gt;

&lt;p&gt;A router says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This data needs to go outside this network. I know where to send it next."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Your Home Router Is Usually More Than Just a Router
&lt;/h2&gt;

&lt;p&gt;This part is important.&lt;/p&gt;

&lt;p&gt;The device we casually call a "router" at home is usually not just a router.&lt;/p&gt;

&lt;p&gt;It often contains multiple things inside one box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Router
Switch
Wi-Fi access point
DHCP server
Firewall/NAT features
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So when you plug an Ethernet cable into your home router, you are usually plugging it into the &lt;strong&gt;switch part&lt;/strong&gt; of the device.&lt;/p&gt;

&lt;p&gt;When your laptop connects through Wi-Fi, it connects through the wireless access point part.&lt;/p&gt;

&lt;p&gt;The real routing happens when data needs to leave your local network and go somewhere else, like the internet.&lt;/p&gt;




&lt;h2&gt;
  
  
  LAN Interface and WAN Interface
&lt;/h2&gt;

&lt;p&gt;A home router usually has two sides:&lt;/p&gt;

&lt;h3&gt;
  
  
  LAN side
&lt;/h3&gt;

&lt;p&gt;This is your local network.&lt;/p&gt;

&lt;p&gt;Your laptop, phone, printer, TV, and other home devices live here.&lt;/p&gt;

&lt;p&gt;Example local IP addresses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.10
192.168.1.11
192.168.1.12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your router may have a local IP like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is often called the &lt;strong&gt;default gateway&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  WAN side
&lt;/h3&gt;

&lt;p&gt;This is the side connected to your internet provider.&lt;/p&gt;

&lt;p&gt;The router gets a public or provider-side IP address on this side.&lt;/p&gt;

&lt;p&gt;So your router sits between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your private home network
The outside internet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How Does a Computer Decide Where to Send Data?
&lt;/h2&gt;

&lt;p&gt;Now comes a very important question.&lt;/p&gt;

&lt;p&gt;Suppose your computer wants to send data to another IP address.&lt;/p&gt;

&lt;p&gt;How does it know whether the destination is inside the same local network or outside?&lt;/p&gt;

&lt;p&gt;It uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Its own IP address
The destination IP address
The subnet mask
The default gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usually, your computer gets these from DHCP.&lt;/p&gt;

&lt;p&gt;A DHCP server may give your device:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP address:       192.168.1.10
Subnet mask:      255.255.255.0
Default gateway:  192.168.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your computer can make a decision.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example 1: Sending Data Inside the Same Network
&lt;/h2&gt;

&lt;p&gt;Let's say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Computer A IP: 192.168.1.10
Computer C IP: 192.168.1.11
Subnet mask:   255.255.255.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Computer A wants to send data to Computer C.&lt;/p&gt;

&lt;p&gt;It checks whether both IP addresses belong to the same network.&lt;/p&gt;

&lt;p&gt;With this subnet mask, both addresses are part of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;192.168.1.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So Computer A understands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Computer C is in my local network.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means Computer A does not need to send the data to the router for routing.&lt;/p&gt;

&lt;p&gt;Instead, it sends an Ethernet frame directly toward Computer C's MAC address.&lt;/p&gt;

&lt;p&gt;Simplified frame:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source MAC: A
Destination MAC: C
Source IP: 192.168.1.10
Destination IP: 192.168.1.11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The switch receives the frame and forwards it to Computer C.&lt;/p&gt;

&lt;p&gt;The router part does not need to be involved.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example 2: Sending Data Outside the Network
&lt;/h2&gt;

&lt;p&gt;Now imagine Computer A wants to send data to:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;That IP is not inside the local network &lt;code&gt;192.168.1.0/24&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So Computer A understands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This destination is outside my network.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now something interesting happens.&lt;/p&gt;

&lt;p&gt;The destination IP stays as:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;But the destination MAC address becomes the MAC address of the router.&lt;/p&gt;

&lt;p&gt;Simplified frame:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source MAC: A
Destination MAC: Router
Source IP: 192.168.1.10
Destination IP: 8.8.8.8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because inside the local network, the computer can only deliver frames to local devices by MAC address.&lt;/p&gt;

&lt;p&gt;To reach the outside world, it sends the frame to the default gateway first.&lt;/p&gt;

&lt;p&gt;The router receives it, looks at the destination IP, and then decides where to send it next.&lt;/p&gt;




&lt;h2&gt;
  
  
  Important Detail: MAC Address Changes, IP Address Stays
&lt;/h2&gt;

&lt;p&gt;This is one of the most useful networking ideas to understand.&lt;/p&gt;

&lt;p&gt;When data moves across networks, the IP packet is trying to reach the final IP address.&lt;/p&gt;

&lt;p&gt;But at each local network hop, the MAC address may change.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your laptop -&amp;gt; Router
Router -&amp;gt; ISP device
ISP device -&amp;gt; next router
Next router -&amp;gt; destination server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each step may use a different source and destination MAC address.&lt;/p&gt;

&lt;p&gt;But the destination IP is still the final server's IP.&lt;/p&gt;

&lt;p&gt;That is why:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Switches care about MAC addresses.
Routers care about IP addresses.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  A Developer-Friendly Example
&lt;/h2&gt;

&lt;p&gt;Imagine you are building a backend API.&lt;/p&gt;

&lt;p&gt;Your laptop is running a frontend app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:5173
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another computer on the same Wi-Fi is running an API server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://192.168.1.25:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When your laptop calls that API, it checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Am I in the same network as 192.168.1.25?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If yes, your laptop sends the frame toward that device's MAC address.&lt;/p&gt;

&lt;p&gt;The switch or Wi-Fi access point handles local delivery.&lt;/p&gt;

&lt;p&gt;The router does not need to send the traffic to the internet.&lt;/p&gt;

&lt;p&gt;Now imagine your app calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.github.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That server is outside your local network.&lt;/p&gt;

&lt;p&gt;So your laptop sends the frame to the router's MAC address.&lt;/p&gt;

&lt;p&gt;The router then forwards the packet toward the internet.&lt;/p&gt;

&lt;p&gt;This is happening all the time while you code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Comparison: Hub vs Switch vs Router
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Understands&lt;/th&gt;
&lt;th&gt;Main Job&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hub&lt;/td&gt;
&lt;td&gt;Layer 1&lt;/td&gt;
&lt;td&gt;Bits/signals&lt;/td&gt;
&lt;td&gt;Sends data to all ports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Layer 2&lt;/td&gt;
&lt;td&gt;MAC addresses&lt;/td&gt;
&lt;td&gt;Sends frames inside a local network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Router&lt;/td&gt;
&lt;td&gt;Layer 3&lt;/td&gt;
&lt;td&gt;IP addresses&lt;/td&gt;
&lt;td&gt;Sends packets between networks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Common Terms You Should Remember
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Frame
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;frame&lt;/strong&gt; belongs to the data link layer.&lt;/p&gt;

&lt;p&gt;It contains MAC address information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source MAC
Destination MAC
Payload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Packet
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;packet&lt;/strong&gt; belongs to the network layer.&lt;/p&gt;

&lt;p&gt;It contains IP address information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source IP
Destination IP
Payload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Segment
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;segment&lt;/strong&gt; usually belongs to TCP at the transport layer.&lt;/p&gt;

&lt;p&gt;It contains port information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source port
Destination port
Data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  MAC address table
&lt;/h3&gt;

&lt;p&gt;A switch uses this table to remember which MAC address is connected to which port.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAC Address    Port
A              1
C              3
D              4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Default gateway
&lt;/h3&gt;

&lt;p&gt;The default gateway is usually your router's local IP address.&lt;/p&gt;

&lt;p&gt;Your computer sends data to the default gateway when the destination is outside the local network.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Simple Mental Model
&lt;/h2&gt;

&lt;p&gt;Here is the easiest way to remember everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hub:
"I will send it to everyone."

Switch:
"I will send it to the correct local device if I know where it is."

Router:
"I will send it to another network."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;Once you understand this, many networking topics become easier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DHCP
ARP
Subnetting
NAT
Docker networking
Kubernetes networking
Cloud VPCs
Firewalls
Load balancers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>networking</category>
      <category>beginners</category>
      <category>computerscience</category>
      <category>webdev</category>
    </item>
    <item>
      <title>DNS Made Simple: What Really Happens Before Your Browser Opens a Website</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Thu, 23 Apr 2026 16:25:15 +0000</pubDate>
      <link>https://dev.to/tahsin000/dns-made-simple-what-really-happens-before-your-browser-opens-a-website-2281</link>
      <guid>https://dev.to/tahsin000/dns-made-simple-what-really-happens-before-your-browser-opens-a-website-2281</guid>
      <description>&lt;p&gt;We use domain names every day.&lt;/p&gt;

&lt;p&gt;We type &lt;code&gt;google.com&lt;/code&gt;, &lt;code&gt;facebook.com&lt;/code&gt;, or &lt;code&gt;linkedin.com&lt;/code&gt; into a browser, press Enter, and the website opens in seconds. It feels simple. Almost boring.&lt;/p&gt;

&lt;p&gt;But under the hood, something very important happens before your browser can even start talking to that website.&lt;/p&gt;

&lt;p&gt;That thing is &lt;strong&gt;DNS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And here is the part many developers miss early on: if you want to understand &lt;strong&gt;TLS/SSL&lt;/strong&gt;, networking, deployment, or even why a request is slow, you need to understand DNS first.&lt;/p&gt;

&lt;p&gt;Because before secure communication begins, your browser has to answer one basic question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Where is this website actually hosted?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's break it down in the simplest possible way.&lt;/p&gt;




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

&lt;h2&gt;
  
  
  First, let's understand the URL
&lt;/h2&gt;

&lt;p&gt;Take this URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://blog.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has a few parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;https&lt;/code&gt; → the scheme or protocol&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;blog&lt;/code&gt; → the subdomain&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;example&lt;/code&gt; → the main domain&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.com&lt;/code&gt; → the top-level domain (TLD)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://engineering.linkedin.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;https&lt;/code&gt; is the protocol&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;engineering&lt;/code&gt; is the subdomain&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;linkedin&lt;/code&gt; is the domain&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.com&lt;/code&gt; is the TLD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure matters because DNS works with these names.&lt;/p&gt;

&lt;p&gt;Before we go into DNS, we need to understand one thing clearly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a domain name is not the real machine address.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is the human-friendly name for that machine.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why domain names exist
&lt;/h2&gt;

&lt;p&gt;Humans are good at remembering words.&lt;/p&gt;

&lt;p&gt;Machines are good at working with numbers.&lt;/p&gt;

&lt;p&gt;That is the heart of the whole idea.&lt;/p&gt;

&lt;p&gt;You can easily remember:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;facebook.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But remembering something like this is much harder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;157.240.22.35
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That number is an IP address.&lt;/p&gt;

&lt;p&gt;An IP address is the real network address of a machine or server.&lt;/p&gt;

&lt;p&gt;So when you type a domain name into a browser, your system has to find the IP address behind that name.&lt;/p&gt;

&lt;p&gt;That translation is what DNS does.&lt;/p&gt;




&lt;h2&gt;
  
  
  A simple real-life example
&lt;/h2&gt;

&lt;p&gt;Think about your home address.&lt;/p&gt;

&lt;p&gt;If someone knows your address, they can find your house.&lt;/p&gt;

&lt;p&gt;Computers work in a similar way.&lt;/p&gt;

&lt;p&gt;Every machine connected to a network needs an address. On the internet, that address is the &lt;strong&gt;IP address&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now imagine you built an app locally on your laptop. Maybe it runs on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That works on your own machine because your machine knows what &lt;code&gt;localhost&lt;/code&gt; means.&lt;/p&gt;

&lt;p&gt;But if you deploy that app to a server on AWS, DigitalOcean, or anywhere else, people cannot visit it using &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They need the address of that server.&lt;/p&gt;

&lt;p&gt;That real address is the IP address.&lt;/p&gt;

&lt;p&gt;But asking users to remember IP addresses is a terrible experience.&lt;/p&gt;

&lt;p&gt;So instead of telling people:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Visit 142.250.183.206
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we give the server a domain name like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myapp.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now people can remember the name, and machines can still connect using the IP.&lt;/p&gt;

&lt;p&gt;That mapping between a human-friendly name and a machine-friendly IP is the whole point of DNS.&lt;/p&gt;




&lt;h2&gt;
  
  
  So what is DNS?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;DNS stands for Domain Name System.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's keep it simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DNS is the system that converts a domain name into an IP address.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You type &lt;code&gt;facebook.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;DNS finds the IP address behind &lt;code&gt;facebook.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Your browser uses that IP to contact the correct server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is called a &lt;strong&gt;system&lt;/strong&gt; because it is not just one thing.&lt;/p&gt;

&lt;p&gt;It involves multiple parts working together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;your browser&lt;/li&gt;
&lt;li&gt;your operating system&lt;/li&gt;
&lt;li&gt;DNS caches&lt;/li&gt;
&lt;li&gt;a DNS resolver&lt;/li&gt;
&lt;li&gt;root name servers&lt;/li&gt;
&lt;li&gt;TLD name servers&lt;/li&gt;
&lt;li&gt;authoritative name servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is why it is not called just "domain name lookup.”&lt;/p&gt;

&lt;p&gt;It is a &lt;strong&gt;system&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before DNS goes to the internet, it checks cache
&lt;/h2&gt;

&lt;p&gt;This is one of the most useful things to understand.&lt;/p&gt;

&lt;p&gt;When you visit a website, your computer does not always start from scratch.&lt;/p&gt;

&lt;p&gt;It first checks whether the answer is already stored somewhere.&lt;/p&gt;

&lt;p&gt;This stored answer is called &lt;strong&gt;cache&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of cache like a shortcut memory.&lt;/p&gt;

&lt;p&gt;If the system already knows the IP address for a domain, it can skip a lot of work.&lt;/p&gt;

&lt;p&gt;That makes everything faster.&lt;/p&gt;

&lt;p&gt;Usually, the lookup goes through these layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Browser cache&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Operating system cache&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DNS resolver cache&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;If not found, then the full DNS lookup starts&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is why websites often open very quickly the second time you visit them.&lt;/p&gt;




&lt;h2&gt;
  
  
  The full DNS journey, step by step
&lt;/h2&gt;

&lt;p&gt;Now let's walk through what actually happens when you type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;facebook.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;into your browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The browser checks its own cache
&lt;/h3&gt;

&lt;p&gt;Your browser first asks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Do I already know the IP for this domain?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If yes, great. It uses that IP immediately.&lt;/p&gt;

&lt;p&gt;If not, it moves to the next step.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. The operating system checks its cache
&lt;/h3&gt;

&lt;p&gt;If the browser does not have the answer, your operating system checks whether it has that domain-to-IP mapping stored.&lt;/p&gt;

&lt;p&gt;If the OS already knows it, it returns the IP to the browser.&lt;/p&gt;

&lt;p&gt;If not, the request continues.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. The system asks a DNS resolver
&lt;/h3&gt;

&lt;p&gt;Now the request goes to a &lt;strong&gt;DNS resolver&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In many cases, this resolver belongs to your ISP, though it could also be a public DNS service.&lt;/p&gt;

&lt;p&gt;Its job is to find the answer for you.&lt;/p&gt;

&lt;p&gt;And just like the browser and OS, the resolver also checks its own cache first.&lt;/p&gt;

&lt;p&gt;If the resolver already knows the IP for &lt;code&gt;facebook.com&lt;/code&gt;, it returns it immediately.&lt;/p&gt;

&lt;p&gt;If not, now the real DNS lookup begins.&lt;/p&gt;




&lt;h2&gt;
  
  
  The resolver starts asking other DNS servers
&lt;/h2&gt;

&lt;p&gt;This is where many learners get confused, but the logic is actually very clean.&lt;/p&gt;

&lt;p&gt;The resolver does not magically know every IP address in the world.&lt;/p&gt;

&lt;p&gt;Instead, it asks the right servers in the right order.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. It asks a root name server
&lt;/h3&gt;

&lt;p&gt;The resolver asks a root name server something like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"I need information about &lt;code&gt;.com&lt;/code&gt;. Where should I go next?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Notice something important:&lt;/p&gt;

&lt;p&gt;It is &lt;strong&gt;not&lt;/strong&gt; asking for the final IP address yet.&lt;/p&gt;

&lt;p&gt;It is asking where the &lt;code&gt;.com&lt;/code&gt; information is managed.&lt;/p&gt;

&lt;p&gt;The root server replies with the address of the &lt;strong&gt;TLD name server&lt;/strong&gt; for &lt;code&gt;.com&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. It asks the TLD name server
&lt;/h3&gt;

&lt;p&gt;Now the resolver goes to the &lt;code&gt;.com&lt;/code&gt; TLD server and asks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Who is responsible for &lt;code&gt;facebook.com&lt;/code&gt;?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Again, this server usually does not return the final website IP directly.&lt;/p&gt;

&lt;p&gt;Instead, it returns the address of the &lt;strong&gt;authoritative name server&lt;/strong&gt; for that domain.&lt;/p&gt;

&lt;p&gt;That server is the source of truth for the domain's DNS records.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. It asks the authoritative name server
&lt;/h3&gt;

&lt;p&gt;Now the resolver asks the authoritative name server:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"What is the IP address for &lt;code&gt;facebook.com&lt;/code&gt;?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This server returns the actual DNS record, such as the IP address.&lt;/p&gt;

&lt;p&gt;Now the resolver finally has the answer it needs.&lt;/p&gt;




&lt;h3&gt;
  
  
  7. The answer comes back and gets cached
&lt;/h3&gt;

&lt;p&gt;Once the resolver gets the IP address, it does two useful things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it returns the answer to your operating system&lt;/li&gt;
&lt;li&gt;it stores the answer in cache for future requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then the OS may cache it too.&lt;/p&gt;

&lt;p&gt;Then the browser may cache it too.&lt;/p&gt;

&lt;p&gt;That means the next lookup can be much faster.&lt;/p&gt;




&lt;h3&gt;
  
  
  8. The browser can finally contact the server
&lt;/h3&gt;

&lt;p&gt;Now your browser has the IP address.&lt;/p&gt;

&lt;p&gt;At this point, it can finally open a network connection to the actual server and send the real HTTP or HTTPS request.&lt;/p&gt;

&lt;p&gt;That is the moment when the website request truly begins.&lt;/p&gt;

&lt;p&gt;So yes, DNS happens &lt;strong&gt;before&lt;/strong&gt; the browser can talk to the web server.&lt;/p&gt;

&lt;p&gt;And that is exactly why DNS matters when learning TLS/SSL.&lt;/p&gt;




&lt;h2&gt;
  
  
  A simple mental model
&lt;/h2&gt;

&lt;p&gt;If all the server names sound too abstract, use this mental model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Root server&lt;/strong&gt; → "I do not know the full answer, but I know who handles &lt;code&gt;.com&lt;/code&gt;.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLD server&lt;/strong&gt; → "I do not know the full answer, but I know who handles &lt;code&gt;facebook.com&lt;/code&gt;.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authoritative server&lt;/strong&gt; → "I am responsible for this domain. Here is the actual answer.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the chain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why DNS is called "resolution”
&lt;/h2&gt;

&lt;p&gt;You may hear the phrase:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DNS resolution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This simply means:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;the process of resolving a domain name into an IP address&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So if someone says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The DNS resolution failed”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;they mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The system could not turn the domain name into an IP address”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No IP, no connection.&lt;br&gt;
No connection, no website.&lt;/p&gt;


&lt;h2&gt;
  
  
  Where subdomains fit into this
&lt;/h2&gt;

&lt;p&gt;Let's say you have a domain like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can create subdomains like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;blog.example.com
api.example.com
admin.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful because one domain can support multiple services.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;blog.example.com&lt;/code&gt; → blog website&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;api.example.com&lt;/code&gt; → backend API&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;admin.example.com&lt;/code&gt; → internal admin dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same parent domain.&lt;br&gt;
Different subdomains.&lt;br&gt;
Different purposes.&lt;/p&gt;

&lt;p&gt;That is why learning domain structure matters before learning DNS deeply.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why websites feel fast after the first visit
&lt;/h2&gt;

&lt;p&gt;A lot of developers notice this but do not always connect it to DNS.&lt;/p&gt;

&lt;p&gt;The first request may take a bit longer because the system needs to find the IP.&lt;/p&gt;

&lt;p&gt;Later requests are faster because the answer may already exist in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;browser cache&lt;/li&gt;
&lt;li&gt;OS cache&lt;/li&gt;
&lt;li&gt;resolver cache&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means the system can skip most of the lookup chain.&lt;/p&gt;

&lt;p&gt;So if a website opens instantly the second time, caching is often part of the reason.&lt;/p&gt;




&lt;h2&gt;
  
  
  Does DNS use TCP or UDP?
&lt;/h2&gt;

&lt;p&gt;In simple learning material, DNS is often explained with &lt;strong&gt;UDP&lt;/strong&gt;, and that is a good starting point.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because UDP is lightweight and fast. It does not need a full connection setup like TCP.&lt;/p&gt;

&lt;p&gt;For many standard DNS queries, that makes it a great fit.&lt;/p&gt;

&lt;p&gt;A simple way to think about it is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNS wants to ask a quick question&lt;/li&gt;
&lt;li&gt;get a quick answer&lt;/li&gt;
&lt;li&gt;and move on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That said, in real systems, DNS can also use TCP in some cases.&lt;/p&gt;

&lt;p&gt;But when you are first learning how DNS feels fast and lightweight, starting with UDP gives you the right intuition.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why DNS matters before TLS/SSL
&lt;/h2&gt;

&lt;p&gt;This is the part many people skip.&lt;/p&gt;

&lt;p&gt;They jump into HTTPS, SSL certificates, and TLS handshakes without asking a more basic question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How did the browser even find the server in the first place?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before secure communication starts, the browser needs to know where to connect.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;resolve the domain name into an IP address&lt;/li&gt;
&lt;li&gt;connect to the server&lt;/li&gt;
&lt;li&gt;then begin TLS/SSL and HTTP communication&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So if DNS is unclear, TLS/SSL will always feel a little foggy too.&lt;/p&gt;

&lt;p&gt;Understanding DNS first makes the next networking topics much easier.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why developers should care about this
&lt;/h2&gt;

&lt;p&gt;It is easy to think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Do I really need to know all this? I can just build apps.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can. For a while.&lt;/p&gt;

&lt;p&gt;But sooner or later, deeper understanding starts to matter.&lt;/p&gt;

&lt;p&gt;Maybe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;your production request is slow&lt;/li&gt;
&lt;li&gt;your domain is not pointing to the right server&lt;/li&gt;
&lt;li&gt;your subdomain is broken&lt;/li&gt;
&lt;li&gt;your SSL setup is failing&lt;/li&gt;
&lt;li&gt;your infrastructure behaves differently across environments&lt;/li&gt;
&lt;li&gt;a tool's official docs feel harder than they should&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where fundamentals help.&lt;/p&gt;

&lt;p&gt;When you understand DNS, you stop treating networking like magic.&lt;/p&gt;

&lt;p&gt;You start seeing the path.&lt;/p&gt;

&lt;p&gt;And once you can see the path, debugging becomes easier.&lt;/p&gt;




&lt;h2&gt;
  
  
  A small story every developer can relate to
&lt;/h2&gt;

&lt;p&gt;Imagine this.&lt;/p&gt;

&lt;p&gt;You deploy your app.&lt;br&gt;
The code is fine.&lt;br&gt;
The server is running.&lt;br&gt;
But the site still does not open.&lt;/p&gt;

&lt;p&gt;At first, you think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;is the backend broken?&lt;/li&gt;
&lt;li&gt;is the port wrong?&lt;/li&gt;
&lt;li&gt;is Nginx failing?&lt;/li&gt;
&lt;li&gt;is HTTPS misconfigured?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the real problem turns out to be simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;the domain is not resolving correctly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That one small DNS issue can make the whole app feel "down.”&lt;/p&gt;

&lt;p&gt;This is why solid developers do not only learn frameworks.&lt;/p&gt;

&lt;p&gt;They learn what happens around the request too.&lt;/p&gt;




&lt;h2&gt;
  
  
  The big lesson: do not skip the basics
&lt;/h2&gt;

&lt;p&gt;A lot of hard topics become easier when your basics are strong.&lt;/p&gt;

&lt;p&gt;Docker makes more sense.&lt;br&gt;
Kubernetes makes more sense.&lt;br&gt;
TLS/SSL makes more sense.&lt;br&gt;
Load balancers, CDNs, proxies, reverse proxies, and hosting all make more sense.&lt;/p&gt;

&lt;p&gt;Not because they are easy.&lt;/p&gt;

&lt;p&gt;But because you already understand the ground they stand on.&lt;/p&gt;

&lt;p&gt;Many developers struggle with official docs not because their English is bad, but because the underlying computer science concepts are still shaky.&lt;/p&gt;

&lt;p&gt;That is normal.&lt;/p&gt;

&lt;p&gt;And the fix is not shortcuts.&lt;/p&gt;

&lt;p&gt;The fix is going back, learning the core ideas properly, and revisiting them again and again until they feel natural.&lt;/p&gt;

&lt;p&gt;That is how real confidence is built.&lt;/p&gt;

</description>
      <category>dns</category>
      <category>networking</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Demystifying TCP: How the Internet Actually Sends Your Data (Without Losing It)</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Mon, 13 Apr 2026 07:58:22 +0000</pubDate>
      <link>https://dev.to/tahsin000/demystifying-tcp-how-the-internet-actually-sends-your-data-without-losing-it-53le</link>
      <guid>https://dev.to/tahsin000/demystifying-tcp-how-the-internet-actually-sends-your-data-without-losing-it-53le</guid>
      <description>&lt;p&gt;Let’s be honest for a second. When we write code to fetch data from a server, we usually don't think twice about how it gets there. We write a simple JavaScript &lt;code&gt;fetch()&lt;/code&gt; call, hit save, and boom our frontend talks to our backend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To us, it feels like magic. We just say "send this," and it arrives. But the Application Layer (where our code lives) is blissfully unaware of the chaotic, noisy, and unpredictable journey that data takes across the internet.&lt;/p&gt;

&lt;p&gt;The real unsung hero making sure your "Hello World" doesn't turn into a corrupted mess of random bytes is the Transport Layer specifically, the TCP (Transmission Control Protocol).&lt;/p&gt;

&lt;p&gt;Today, we are going to look under the hood. No dry, boring textbook definitions. Just a practical, developer-friendly look at how TCP actually works, how it keeps our data safe, and why understanding it will make you a much better software engineer.&lt;/p&gt;




&lt;h3&gt;
  
  
  What is TCP, Really?
&lt;/h3&gt;

&lt;p&gt;Imagine you are mailing a 1,000-page manuscript to a publisher, but the post office only allows you to send one page per envelope.&lt;/p&gt;

&lt;p&gt;If you just dump 1,000 envelopes into the mailbox, what happens? Some might get lost. Some might arrive out of order. The publisher would be hopelessly confused.&lt;/p&gt;

&lt;p&gt;TCP is the ultimate postal manager. It chops your big data into smaller pieces called &lt;strong&gt;segments&lt;/strong&gt;, numbers them, sends them, and waits for a receipt. If a piece goes missing or gets corrupted, TCP demands that it be sent again.&lt;/p&gt;

&lt;p&gt;That’s why the "C" in TCP stands for &lt;strong&gt;Control&lt;/strong&gt;. It controls the transmission so you don't have to.&lt;/p&gt;

&lt;p&gt;To do this, TCP breaks communication down into three distinct phases:&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;The Setup&lt;/strong&gt; (Three-way Handshake)&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;The Data Transfer&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;The Teardown&lt;/strong&gt; (Four-way Finishing)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s walk through them.&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 1: The Three-Way Handshake 🤝
&lt;/h3&gt;

&lt;p&gt;Before TCP sends a single byte of your actual data, it needs to make sure the server is awake, willing, and ready to talk. It does this using a process called the Three-Way Handshake.&lt;/p&gt;

&lt;p&gt;Imagine calling a friend on the phone:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;You:&lt;/strong&gt; "Hey, are you there? Can you hear me?" &lt;em&gt;(SYN)&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Friend:&lt;/strong&gt; "Yeah, I hear you! Can you hear me?" &lt;em&gt;(SYN-ACK)&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;You:&lt;/strong&gt; "Loud and clear. Let's talk." &lt;em&gt;(ACK)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In TCP terms, it looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SYN (Synchronize):&lt;/strong&gt; The Client sends a packet with the SYN flag turned on. It says, "I want to connect, and I'm starting my sequence at number 1000."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SYN-ACK (Synchronize-Acknowledge):&lt;/strong&gt; The Server replies. "I got your request (ACK 1001), and I also want to connect. My sequence starts at 2000" (SYN).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACK (Acknowledge):&lt;/strong&gt; The Client sends one final confirmation. "Got it. I'm ready for your data starting at 2001."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Boom. The connection is established. Now, they can safely send data.&lt;/p&gt;




&lt;h3&gt;
  
  
  What’s Inside a TCP Segment? (The Anatomy of a Header)
&lt;/h3&gt;

&lt;p&gt;When TCP chops up your data, it doesn't just send raw text. It wraps your data in a &lt;strong&gt;Header&lt;/strong&gt; a block of metadata that contains all the instructions for delivery.&lt;/p&gt;

&lt;p&gt;A TCP header is usually between 20 and 60 bytes. Let's break down the coolest parts of this header.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. The Ports (Source &amp;amp; Destination)
&lt;/h4&gt;

&lt;p&gt;You probably know that an HTTP server runs on port 80, HTTPS on 443, and your local React app maybe on 3000. But have you ever wondered what port the client (your browser) uses to make the request?&lt;/p&gt;

&lt;p&gt;The TCP header reserves 16 bits each for the Source Port and the Destination Port. 16 bits means $2^{16} - 1$, which gives us a maximum of 65,535 possible ports.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Well-known ports (0 - 1023):&lt;/strong&gt; Reserved for big stuff. (80 for HTTP, 443 for HTTPS, 22 for SSH).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registered ports (1024 - 49151):&lt;/strong&gt; Used by specific apps (like MySQL on 3306).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ephemeral / Dynamic ports (49152 - 65535):&lt;/strong&gt; This is the secret sauce! &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When your browser makes a request to Facebook (port 443), your Operating System randomly grabs an unused Ephemeral port (let's say 50153) and assigns it to your browser. So the request goes from &lt;code&gt;Your_IP:50153&lt;/code&gt; to &lt;code&gt;Facebook_IP:443&lt;/code&gt;. When Facebook replies, it knows exactly to send the data back to port 50153, so it reaches your exact browser tab!&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Sequence &amp;amp; Acknowledgment Numbers
&lt;/h4&gt;

&lt;p&gt;These are the page numbers of our manuscript analogy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sequence Number:&lt;/strong&gt; "This is byte number 1001 of my data."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACK Number:&lt;/strong&gt; "I successfully received up to byte 1005. Please send byte 1006 next."&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Window Size (Flow Control)
&lt;/h4&gt;

&lt;p&gt;Imagine trying to drink from a firehose. You'd drown. Servers can experience the same thing if a client sends data too fast.&lt;/p&gt;

&lt;p&gt;The Window Size is the server politely saying: "Listen, I can only handle 10,000 bytes at a time right now. Don't send me more than that until I acknowledge receipt, or I'll crash." This prevents overwhelming the receiver.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. The Checksum (Error Detection)
&lt;/h4&gt;

&lt;p&gt;As data travels across the ocean through fiber optic cables, routers, and Wi-Fi signals, electrical interference can flip a bit (turn a 0 into a 1). Your "I love you" might suddenly turn into "I hate you".&lt;/p&gt;

&lt;p&gt;To fix this, TCP uses a Checksum. Before sending, the sender takes all the data, adds it up in a specific binary way, flips the bits (One's Complement), and puts that value in the Checksum field.&lt;/p&gt;

&lt;p&gt;When the receiver gets it, they do the exact same math. If their result doesn't perfectly match, they know the data got corrupted in transit. They silently drop the corrupted segment, forcing the sender to re-transmit it.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Flags
&lt;/h4&gt;

&lt;p&gt;These are tiny 1-bit switches that tell the receiver what kind of segment this is. Is it a setup request (SYN)? Is it an acknowledgment (ACK)? Or is it time to close the connection (FIN)?&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 2: Sending the Data
&lt;/h3&gt;

&lt;p&gt;Once the handshake is done, the actual data transfer begins.&lt;/p&gt;

&lt;p&gt;Let's say we are sending the string "Hello World". Based on the Maximum Segment Size (MSS) agreed upon during the handshake, TCP might split this into multiple segments.&lt;/p&gt;

&lt;p&gt;The client sends "Hell", the server ACKs it. The client sends "o Wo", the server ACKs it.&lt;/p&gt;

&lt;p&gt;Because of the Window Size, the client doesn't actually have to wait for an ACK after every single segment. If the window is large enough, it can blast 10 segments at once, and the server can send a single ACK saying, "Yep, got all 10!"&lt;/p&gt;

&lt;p&gt;If an ACK never arrives, the sender's internal timer runs out, and it assumes the data was lost in the void. It then resends the data. That's the beauty of it it guarantees delivery.&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 3: The Four-Way Teardown 👋
&lt;/h3&gt;

&lt;p&gt;When the client is done sending data, it doesn't just hang up the phone. It's polite. It initiates a Four-Way Teardown.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client:&lt;/strong&gt; Sends a FIN (Finish) flag. &lt;em&gt;"I'm done sending data."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server:&lt;/strong&gt; Sends an ACK. &lt;em&gt;"Understood, you're done."&lt;/em&gt; (At this point, the server might still have a little bit of its own data left to send back to the client. The client will wait and listen).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server:&lt;/strong&gt; Sends its own FIN. &lt;em&gt;"Okay, I'm done sending data too."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client:&lt;/strong&gt; Sends a final ACK. &lt;em&gt;"Got it. Goodbye forever."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The connection is closed, and the OS frees up the ephemeral port to be used by another application later.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Should You Care as a Developer?
&lt;/h3&gt;

&lt;p&gt;You might be thinking, "This is cool, but my framework handles this. Why do I need to know it?"&lt;/p&gt;

&lt;p&gt;Because things break.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When your API requests start timing out, understanding the Three-way Handshake helps you debug if a firewall is blocking your SYN packets.&lt;/li&gt;
&lt;li&gt;When you wonder why you can't run two node servers on port 3000, you now understand how Ports bind to processes.&lt;/li&gt;
&lt;li&gt;When you design high-traffic systems, understanding Window Size helps you realize why servers get overwhelmed and drop connections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding TCP is like moving from driving an automatic car to a manual transmission. You don't have to think about the gears every day, but when you're stuck in the mud, knowing exactly how the engine connects to the wheels is what gets you out.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>tcp</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why We Talk OSI but Live in a TCP/IP World (A Developer’s Guide)</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Sun, 12 Apr 2026 10:55:37 +0000</pubDate>
      <link>https://dev.to/tahsin000/why-we-talk-osi-but-live-in-a-tcpip-world-a-developers-guide-140o</link>
      <guid>https://dev.to/tahsin000/why-we-talk-osi-but-live-in-a-tcpip-world-a-developers-guide-140o</guid>
      <description>&lt;p&gt;If you’ve ever sat in a tech meeting and nodded along while another engineer threw around terms like "Layer 7 load balancing" or "L4 routing," you aren't alone. &lt;/p&gt;

&lt;p&gt;We talk about networking a lot in software development, but there’s a funny quirk in our industry: the model we learn in textbooks isn't exactly the model that runs the internet. &lt;/p&gt;

&lt;p&gt;In our last deep dive, we talked about the OSI model a beautiful, theoretical 7-layer philosophy. But out in the wild? The entire world runs on the &lt;strong&gt;TCP/IP model&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Today, let's bridge the gap between theory and reality, figure out how data actually moves across the internet, and look at the only layers you actually need to care about as a software engineer.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Reality Check: 7 Layers vs. 5 Layers
&lt;/h3&gt;

&lt;p&gt;The OSI model breaks networking down into 7 distinct layers. But the TCP/IP model, which is what actually powers the internet today, condenses things down to just 5 layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Application Layer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transport Layer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network Layer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data Link Layer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Physical Layer&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Wait, what happened to the &lt;strong&gt;Presentation&lt;/strong&gt; and &lt;strong&gt;Session&lt;/strong&gt; layers from the OSI model? &lt;/p&gt;

&lt;p&gt;In the real world, they didn't disappear; they just got absorbed. When you are building a modern web app say, a Nuxt.js frontend communicating with a Laravel backend your browser and framework handle everything at once. &lt;/p&gt;

&lt;p&gt;When you type "Hello" in a chat app, the Application Layer formats that text into JSON (what the Presentation layer used to do), compresses it, converts it to binary, and even checks if the other person is online with that little green dot (what the Session layer used to do). Because the Application Layer handles all of this heavy lifting, the TCP/IP model just groups them together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Crucial Developer Rule:&lt;/strong&gt; Even though the TCP/IP model condensed the top layers, we still use OSI numbering in our everyday developer conversations! We still call the Application Layer &lt;strong&gt;L7&lt;/strong&gt;. We call the Transport layer &lt;strong&gt;L4&lt;/strong&gt;, Network is &lt;strong&gt;L3&lt;/strong&gt;, and Data Link is &lt;strong&gt;L2&lt;/strong&gt;. If you ever call the Application layer "L5," other engineers will look at you funny. Always stick to the L7 terminology!&lt;/p&gt;




&lt;h3&gt;
  
  
  Layer 4: The Transport Layer (TCP vs. UDP)
&lt;/h3&gt;

&lt;p&gt;Once your application has prepped the data, it hits the Transport Layer. This is where we decide &lt;em&gt;how&lt;/em&gt; the data is going to travel, and you have two main choices: &lt;strong&gt;TCP&lt;/strong&gt; or &lt;strong&gt;UDP&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  TCP (Transmission Control Protocol)
&lt;/h4&gt;

&lt;p&gt;Think of TCP as the highly reliable, slightly slower courier who requires a signature on delivery. It is 100% controlled. &lt;/p&gt;

&lt;p&gt;Imagine you are sending a text message that says "I LOVE YOU." If the data gets scrambled and arrives as "O I V E U Y," you're going to have a bad time. For text, JSON payloads, important API requests, or critical database transactions, we use TCP. It ensures every single piece of data arrives in the exact right order. When using TCP, your data is broken down into chunks called &lt;strong&gt;Segments&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  UDP (User Datagram Protocol)
&lt;/h4&gt;

&lt;p&gt;UDP is the fast, reckless delivery driver throwing newspapers onto your porch without stopping. It doesn't care if a few get lost in the bushes. &lt;/p&gt;

&lt;p&gt;We use UDP for things like live video streaming. If a stream contains 10 million frames and a couple of them drop out, your screen might glitch for a fraction of a second, but the video keeps playing. You wouldn't want the whole live stream to pause just to retrieve one missing frame. When using UDP, your data is broken down into chunks called &lt;strong&gt;Datagrams&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Moving Down the Stack: L3 to L1
&lt;/h3&gt;

&lt;p&gt;After the Transport Layer, the data keeps moving down the chain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Network Layer (L3):&lt;/strong&gt; This is where IP addresses come in. Your data (the Segment or Datagram) gets tagged with the Sender's IP and the Receiver's IP. Once those are attached, the whole package is now called a &lt;strong&gt;Packet&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Link Layer (L2):&lt;/strong&gt; Here, we attach MAC addresses to figure out the physical hardware hops the packet needs to take.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Physical Layer (L1):&lt;/strong&gt; Finally, everything is converted into 1s and 0s raw electrical signals or light pulses shooting through cables. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;A quick note for my fellow software engineers:&lt;/em&gt; You really only need to master L7, L4, L3, and L2. Unless you have a burning desire to become an electrical engineer, you can safely let the hardware folks worry about the Physical Layer!&lt;/p&gt;




&lt;h3&gt;
  
  
  A Quick Trip Back to 1969
&lt;/h3&gt;

&lt;p&gt;You might be wondering: if OSI is the standard, why is TCP/IP so different? &lt;/p&gt;

&lt;p&gt;It actually comes down to the Cold War. In 1969, the US Defense Department created an organization called ARPANET. They needed a decentralized network where data could survive even if computers or physical locations were destroyed in a war. Over the next decade, they actively developed the TCP/IP model. &lt;/p&gt;

&lt;p&gt;It was messy, organic, and random. In fact, TCP was being used to send data long before IP addresses were even a standard! The beautifully organized, perfectly logical OSI model didn't actually come along until 1984 to try and make sense of it all. We teach OSI first because it's fundamentally easier to understand, but TCP/IP is the battle-tested system that won the internet.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>webdev</category>
      <category>computerscience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Demystifying Linux: How GNU, Shells, and Terminals Actually Work Together</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Tue, 07 Apr 2026 10:09:39 +0000</pubDate>
      <link>https://dev.to/tahsin000/demystifying-linux-how-gnu-shells-and-terminals-actually-work-together-4975</link>
      <guid>https://dev.to/tahsin000/demystifying-linux-how-gnu-shells-and-terminals-actually-work-together-4975</guid>
      <description>&lt;p&gt;If you've been working with Linux for a while, you probably know that "Linux" technically just refers to the kernel. But a kernel alone is not enough to give you a working computer. To get a complete Operating System (what we call a Linux Distribution, like Ubuntu or Fedora), you need a lot of other moving parts.&lt;/p&gt;

&lt;p&gt;Today, we're going to peel back the layers of a Linux operating system. We'll look at where the tools we use every day actually come from, the difference between a terminal and a shell, and what happens behind the scenes when you type a simple command.&lt;/p&gt;

&lt;p&gt;Let's dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Origin Story: Enter Richard Stallman and GNU
&lt;/h2&gt;

&lt;p&gt;To understand how Linux works today, we have to travel back to 1983. Back then, an operating system called Unix was highly popular among universities and large companies. The problem? Unix was proprietary and expensive.&lt;/p&gt;

&lt;p&gt;A programmer named &lt;strong&gt;Richard Stallman&lt;/strong&gt; didn't like this. He believed software, especially operating systems, should be free and accessible to everyone. So, he started the &lt;strong&gt;Free Software Foundation (FSF)&lt;/strong&gt; and launched the &lt;strong&gt;GNU Project&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fun fact: GNU is a recursive acronym that stands for "GNU's Not Unix!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Stallman's team began building free, open-source replacements for all the essential pieces of Unix. Their plan was to build everything needed for an OS, so that anyone students, devs, or companies could piece together a free operating system.&lt;/p&gt;

&lt;p&gt;If you use open-source tools today, you owe a huge "thank you" to Stallman and the FSF.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Essential GNU Toolkit
&lt;/h2&gt;

&lt;p&gt;So, what exactly did the GNU project build? They created a massive bundle of tools that bridge the gap between human developers and the kernel. Here are the heavy hitters:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. GCC (GNU Compiler Collection)
&lt;/h3&gt;

&lt;p&gt;If you've ever written a C program, you know you can't just run the raw text. You need to compile it into binary machine code that the computer understands. GCC is the legendary compiler that makes this happen. Without it, the open-source world as we know it wouldn't exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. glibc (GNU C Library)
&lt;/h3&gt;

&lt;p&gt;This one is fascinating. When you write a simple &lt;code&gt;printf("Hello World");&lt;/code&gt; in C, did you know that &lt;code&gt;printf&lt;/code&gt; isn't actually a native part of the C language?&lt;/p&gt;

&lt;p&gt;Native C handles things like &lt;code&gt;if/else' statements and&lt;/code&gt;for' loops. But interacting with hardware (like printing to a screen, allocating memory, or reading files) requires talking to the kernel. &lt;strong&gt;glibc&lt;/strong&gt; is the massive library that provides functions like &lt;code&gt;printf&lt;/code&gt;, &lt;code&gt;scanf&lt;/code&gt;, and &lt;code&gt;malloc&lt;/code&gt;. It acts as a translator, taking your code and making the complex "system calls" to the kernel on your behalf.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. GNU Coreutils
&lt;/h3&gt;

&lt;p&gt;This is the toolbox you use every single day. Have you ever typed &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;cp&lt;/code&gt;, or &lt;code&gt;rm&lt;/code&gt;?&lt;br&gt;
These aren't just random words; they are individual, standalone programs bundled together in what we call the &lt;strong&gt;GNU Core Utilities&lt;/strong&gt; (or Coreutils). They run in the "user space" and allow you to interact with your system.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Visual Layer: Desktop Environments (DE)
&lt;/h2&gt;

&lt;p&gt;Okay, so we have the kernel (the engine) and the GNU utilities (the steering wheel and pedals). But how do we actually see what we are doing?&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;Desktop Environments (DE)&lt;/strong&gt; come in. When you install an OS and see a taskbar, window frames, a file explorer, and icons, you are looking at the DE.&lt;/p&gt;

&lt;p&gt;Here are a few popular ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GNOME:&lt;/strong&gt; The default for Ubuntu, Fedora, and Debian. It's modern and beginner-friendly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KDE Plasma:&lt;/strong&gt; Popular on Arch and openSUSE. It's incredibly customizable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aqua:&lt;/strong&gt; The proprietary desktop environment used by Apple for macOS (which includes the Finder and the Dock).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Desktop Environment is also responsible for giving you a &lt;strong&gt;Terminal&lt;/strong&gt;. On Ubuntu (GNOME), it's called GNOME Terminal. On KDE, it's called Konsole. The terminal is just a graphical window an interface that lets you type things. But it doesn't process the commands itself. For that, it needs a Shell.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Brains of the Operation: The Shell
&lt;/h2&gt;

&lt;p&gt;If the Terminal is just a blank window, the &lt;strong&gt;Shell&lt;/strong&gt; is the smart program running inside it.&lt;/p&gt;

&lt;p&gt;The Shell takes the text you type, interprets it, figures out what program you want to run (like an &lt;code&gt;ls&lt;/code&gt; command from the Coreutils), and hands that request over to the kernel. When the kernel is done, the Shell takes the output and prints it on your Terminal screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Quick History of Shells:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;sh (Bourne Shell):&lt;/strong&gt; Created by Stephen Bourne at Bell Labs in 1977. The OG.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ksh (KornShell):&lt;/strong&gt; Created by David Korn in 1983, adding more features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;bash (Bourne Again Shell):&lt;/strong&gt; The GNU project's free answer to the original Bourne shell. It became the default for almost all Linux distributions for decades.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;zsh (Z Shell):&lt;/strong&gt; A modern, highly customizable shell. If you use a modern Mac, &lt;code&gt;zsh&lt;/code&gt; is now the default&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>cli</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Stop Calling Docker a Tool: The Real Story Behind 'docker run hello-world'</title>
      <dc:creator>Tahsin Abrar</dc:creator>
      <pubDate>Mon, 06 Apr 2026 10:57:28 +0000</pubDate>
      <link>https://dev.to/tahsin000/docker-is-more-than-a-tool-understanding-the-docker-ecosystem-2ani</link>
      <guid>https://dev.to/tahsin000/docker-is-more-than-a-tool-understanding-the-docker-ecosystem-2ani</guid>
      <description>&lt;p&gt;Let’s get one thing straight right out of the gate: &lt;strong&gt;Docker is not just a tool.&lt;/strong&gt; It’s not just a simple application, and it’s certainly not just a piece of standalone software. &lt;/p&gt;

&lt;p&gt;If someone tells you Docker is just a software tool, you can confidently tell them they’ve been misled. &lt;/p&gt;

&lt;p&gt;So, what is it? &lt;strong&gt;Docker is a platform. It is an ecosystem.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To truly master Docker, you have to stop looking at it as a black box that magically runs your code, and start looking at it as a living, breathing ecosystem. Today, we are going to dive deep into how this ecosystem actually works.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The Ecosystem Analogy
&lt;/h2&gt;

&lt;p&gt;Think about a biological ecosystem a food chain. An earthworm is eaten by a duck, the duck is caught by a snake, the snake is hunted by a mongoose, and the mongoose is swooped up by an eagle. &lt;/p&gt;

&lt;p&gt;For the ecosystem to function, every single piece of that chain has to exist and interact. Docker works exactly the same way. It is a chain of distinct technologies working together to create what we call the "Docker Platform."&lt;/p&gt;

&lt;p&gt;Before we look at the chain in action, let’s meet the main characters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker Client (CLI):&lt;/strong&gt; The interface where you type your commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Engine (dockerd):&lt;/strong&gt; The background daemon (the brain) that listens for API requests and manages Docker objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Desktop:&lt;/strong&gt; The unsung hero for Mac and Windows users. It quietly creates a Linux Virtual Machine in the background so the Docker Engine has a Linux kernel to work with.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Images:&lt;/strong&gt; Think of an image as a "screenshot" or a frozen snapshot of a container. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Hub:&lt;/strong&gt; The massive, cloud-based database where all these images (like Ubuntu, Redis, Postgres, or Node) live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Compose:&lt;/strong&gt; (We’ll save this one for a future post, but just know it’s the orchestrator for multi-container setups!)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Deep Dive: What actually happens when you hit Enter?
&lt;/h2&gt;

&lt;p&gt;Most developers know how to type &lt;code&gt;docker run hello-world&lt;/code&gt;. But what happens in the milliseconds after you hit enter? Let’s connect the dots.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Step 1: The Request
&lt;/h3&gt;

&lt;p&gt;You type &lt;code&gt;docker run hello-world&lt;/code&gt; into your terminal. The &lt;strong&gt;Docker Client&lt;/strong&gt; catches this command and translates it into a REST API request. It sends this request to the &lt;strong&gt;Docker Engine&lt;/strong&gt; (specifically, the &lt;code&gt;dockerd&lt;/code&gt; daemon).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Passing the Baton
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;dockerd&lt;/code&gt; is a busy manager. It receives your request and says, &lt;em&gt;"Hey, **containerd&lt;/em&gt;* (the high-level container runtime), handle this for me."*&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: The Cache Check
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;containerd&lt;/code&gt; acts like a smart librarian. First, it checks its local cache. It asks: &lt;em&gt;"Do we already have the &lt;code&gt;hello-world&lt;/code&gt; image downloaded on this computer?"&lt;/em&gt; If this is your first time running it, the answer is no. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: The Download (Pulling)
&lt;/h3&gt;

&lt;p&gt;Because the image isn't stored locally, &lt;code&gt;containerd&lt;/code&gt; reaches out to &lt;strong&gt;Docker Hub&lt;/strong&gt;. It requests the &lt;code&gt;hello-world&lt;/code&gt; image, pulls it down, and caches it locally so it won't have to download it again next time. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: The Build
&lt;/h3&gt;

&lt;p&gt;Now that it has the image, &lt;code&gt;containerd&lt;/code&gt; hands it over to &lt;strong&gt;runc&lt;/strong&gt; (the low-level runtime) and says, &lt;em&gt;"Execute this."&lt;/em&gt; ### Step 6: The Kernel Magic&lt;br&gt;
Here is where the real magic happens. &lt;code&gt;runc&lt;/code&gt; talks directly to the &lt;strong&gt;Linux Kernel&lt;/strong&gt; (which, if you are on Mac/Windows, is provided by Docker Desktop). &lt;/p&gt;

&lt;p&gt;It asks the kernel for two very specific things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Namespaces:&lt;/strong&gt; To create an isolated "alternate reality" for the container so it can't see what else is running on your machine.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Control Groups (cgroups):&lt;/strong&gt; To set strict limits on how much RAM, CPU, and Hard Drive space this specific container is allowed to use.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The kernel agrees, builds this isolated little world, and the container is born!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7: The Response
&lt;/h3&gt;

&lt;p&gt;A new process starts inside that container, executes the &lt;code&gt;hello-world&lt;/code&gt; script, and sends a success message all the way back up the chain from the daemon, to the CLI, and finally onto your screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens if you run it a second time?&lt;/strong&gt;&lt;br&gt;
Try running &lt;code&gt;docker run hello-world&lt;/code&gt; again. Notice how much faster it is? It completely skips Docker Hub. &lt;code&gt;containerd&lt;/code&gt; finds the image in the local cache, hands it straight to &lt;code&gt;runc&lt;/code&gt;, and the container spins up instantly. &lt;/p&gt;

&lt;h2&gt;
  
  
  The "Just Make it Work" Trap
&lt;/h2&gt;

&lt;p&gt;You might be wondering: &lt;em&gt;Why do I need to know all of this?&lt;/em&gt; Here is a hard truth: there are software engineers out there with 5 to 10 years of experience who couldn't explain what you just read. They never dive deep. They treat Docker as a magical black box because their only goal is to "just make it work." &lt;/p&gt;

&lt;p&gt;It’s easy to be lazy. It's easy to just copy-paste terminal commands. But taking the easy route puts a hard ceiling on your career.&lt;/p&gt;

&lt;p&gt;Think of your brain like a massive library. If you just throw random facts into it without organizing them, you'll never be able to find the information when a server crashes at 2 AM. But if you take the time to &lt;strong&gt;connect the dots&lt;/strong&gt; if you organize your knowledge logically, understanding &lt;em&gt;how&lt;/em&gt; &lt;code&gt;dockerd&lt;/code&gt; talks to &lt;code&gt;containerd&lt;/code&gt; you create a mental index. &lt;/p&gt;

&lt;p&gt;When you learn this way, you never forget. &lt;/p&gt;

</description>
      <category>docker</category>
      <category>containers</category>
      <category>devops</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
