<?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: CodeWithDhanian</title>
    <description>The latest articles on DEV Community by CodeWithDhanian (@code_2).</description>
    <link>https://dev.to/code_2</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2598648%2F680b87c2-d957-4cdd-b8c1-0009b0f55328.jpg</url>
      <title>DEV Community: CodeWithDhanian</title>
      <link>https://dev.to/code_2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/code_2"/>
    <language>en</language>
    <item>
      <title>Day 5: Inserting Data – INSERT INTO, Multiple Rows, and RETURNING</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Sun, 24 May 2026 12:25:46 +0000</pubDate>
      <link>https://dev.to/code_2/day-5-inserting-data-insert-into-multiple-rows-and-returning-19bi</link>
      <guid>https://dev.to/code_2/day-5-inserting-data-insert-into-multiple-rows-and-returning-19bi</guid>
      <description>&lt;h3&gt;
  
  
  Introduction: Why Data Insertion Matters in Real-World Development
&lt;/h3&gt;

&lt;p&gt;In any production database system, inserting data is the primary way information enters your application. Whether you are building a user registration flow, logging e-commerce orders, importing CSV analytics data, or syncing IoT sensor readings, the &lt;code&gt;INSERT&lt;/code&gt; statement is the gateway between your application code and persistent storage.&lt;/p&gt;

&lt;p&gt;Mastering insertion is not just about syntax — it directly impacts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application performance (single-row vs. bulk operations)&lt;/li&gt;
&lt;li&gt;Data integrity (handling defaults, constraints, and generated values)&lt;/li&gt;
&lt;li&gt;User experience (returning fresh IDs or computed fields instantly)&lt;/li&gt;
&lt;li&gt;Scalability (avoiding costly round-trips between app and database)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end of this tutorial you will confidently insert single records, bulk-load hundreds or thousands of rows efficiently, retrieve auto-generated values in one atomic operation using the &lt;code&gt;RETURNING&lt;/code&gt; clause (PostgreSQL), and apply production-grade best practices that senior engineers use daily.&lt;/p&gt;

&lt;p&gt;We will use &lt;strong&gt;PostgreSQL&lt;/strong&gt; for the main examples because the &lt;code&gt;RETURNING&lt;/code&gt; clause is native and extremely powerful here. MySQL equivalents and differences are clearly noted so you can apply the same concepts regardless of your stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The INSERT INTO Statement – Core Concepts
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;INSERT&lt;/code&gt; statement tells the database: “Here is new data — please store it according to the table’s structure.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Syntax&lt;/strong&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;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;column2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="n"&gt;columnN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="n"&gt;valueN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;You explicitly list the columns you want to populate.&lt;/li&gt;
&lt;li&gt;The database fills any omitted columns with their &lt;code&gt;DEFAULT&lt;/code&gt; value or &lt;code&gt;NULL&lt;/code&gt; (if allowed).&lt;/li&gt;
&lt;li&gt;Order of values must match the order of columns in the parentheses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why list columns explicitly?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It makes your code resilient to future schema changes (new columns added later) and improves readability/maintainability.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Inserting a Single Row – Step-by-Step
&lt;/h3&gt;

&lt;p&gt;Assume we have this table (created in Day 4):&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;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;product_id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;-- Auto-incrementing ID (PostgreSQL)&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="nb"&gt;NUMERIC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;NOW&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;&lt;strong&gt;Single-row insertion example&lt;/strong&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="c1"&gt;-- Example 1: Full column list (most explicit and safest)&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;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Wireless Bluetooth Headphones'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;89&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Example 2: Omit columns that have defaults or are auto-generated&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;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'USB-C Cable'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What happens behind the scenes&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Database validates constraints (NOT NULL, data types, CHECK constraints).&lt;/li&gt;
&lt;li&gt;Generates default values where needed.&lt;/li&gt;
&lt;li&gt;Writes the row to disk (within a transaction).&lt;/li&gt;
&lt;li&gt;Returns success or raises an error.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;MySQL note&lt;/strong&gt;: Use the same syntax. The &lt;code&gt;SERIAL&lt;/code&gt; type becomes &lt;code&gt;AUTO_INCREMENT&lt;/code&gt; and the primary key.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Inserting Multiple Rows Efficiently
&lt;/h3&gt;

&lt;p&gt;Inserting rows one by one in a loop is a performance anti-pattern. Databases are optimized for set-based operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-row INSERT syntax&lt;/strong&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;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; 
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Smart Watch'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;249&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Laptop Stand'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Wireless Mouse'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One network round-trip instead of dozens.&lt;/li&gt;
&lt;li&gt;Single transaction → atomicity.&lt;/li&gt;
&lt;li&gt;Database can optimize batch writing and indexing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Production tip&lt;/strong&gt;: For thousands of rows, use PostgreSQL’s &lt;code&gt;COPY&lt;/code&gt; command or prepared statements with batching in your application language (e.g., &lt;code&gt;pg&lt;/code&gt; driver in Node.js with &lt;code&gt;multi-row&lt;/code&gt; mode).&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Handling NULL, DEFAULT, and Constraints
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Explicitly set NULL (only if column allows it)&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;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Test Product'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Let DEFAULT kick in&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;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Free Sample Item'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: Never rely on implicit column order for critical applications. Always name columns.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. The RETURNING Clause – The Magic of Getting Data Back Instantly (PostgreSQL)
&lt;/h3&gt;

&lt;p&gt;One of the most powerful features in PostgreSQL. After inserting, you can immediately retrieve any columns — especially auto-generated IDs, timestamps, or computed values — without a second &lt;code&gt;SELECT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax&lt;/strong&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;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'4K Webcam'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;129&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;RETURNING&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                    &lt;span class="c1"&gt;-- Return every column&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Practical examples&lt;/strong&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="c1"&gt;-- Return only the new ID and creation timestamp&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;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Mechanical Keyboard'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;79&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;RETURNING&lt;/span&gt; &lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Return multiple rows when inserting many&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;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; 
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'HDMI Cable'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Monitor Arm'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;RETURNING&lt;/span&gt; &lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real-world use case&lt;/strong&gt;: In a REST API, when a user creates a new order, you can return the full order object (including the generated &lt;code&gt;order_id&lt;/code&gt;) in the same HTTP response. No extra query needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MySQL equivalent (versions 8.0.21+)&lt;/strong&gt;: MySQL now supports &lt;code&gt;RETURNING&lt;/code&gt; in INSERT, but older versions require &lt;code&gt;LAST_INSERT_ID()&lt;/code&gt; after the insert:&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="c1"&gt;-- MySQL alternative&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;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Example'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;LAST_INSERT_ID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Best Practices &amp;amp; Production Techniques
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always name columns&lt;/strong&gt; — never use &lt;code&gt;INSERT INTO table VALUES (...)&lt;/code&gt; in production code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use parameterized queries / prepared statements&lt;/strong&gt; to prevent SQL injection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch inserts&lt;/strong&gt; for bulk data (100–10,000 rows).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wrap in transactions&lt;/strong&gt; when inserting related data across multiple tables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate data in the application layer&lt;/strong&gt; before hitting the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor insert performance&lt;/strong&gt; with &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; on large operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consider ON CONFLICT&lt;/strong&gt; (PostgreSQL) or &lt;code&gt;INSERT ... ON DUPLICATE KEY UPDATE&lt;/code&gt; (MySQL) for upsert patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example of safe, parameterized insert (conceptual — shown in SQL for clarity)&lt;/strong&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="c1"&gt;-- In application code you would use placeholders&lt;/span&gt;
&lt;span class="k"&gt;PREPARE&lt;/span&gt; &lt;span class="n"&gt;insert_product&lt;/span&gt; &lt;span class="k"&gt;AS&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;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;RETURNING&lt;/span&gt; &lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. Common Pitfalls &amp;amp; Troubleshooting
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pitfall&lt;/th&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting column names&lt;/td&gt;
&lt;td&gt;Data goes into wrong columns&lt;/td&gt;
&lt;td&gt;Always list columns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Violating NOT NULL&lt;/td&gt;
&lt;td&gt;Error: null value in column&lt;/td&gt;
&lt;td&gt;Provide value or DEFAULT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type mismatch&lt;/td&gt;
&lt;td&gt;Error: invalid input syntax&lt;/td&gt;
&lt;td&gt;Cast or format correctly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting RETURNING&lt;/td&gt;
&lt;td&gt;Extra SELECT query needed&lt;/td&gt;
&lt;td&gt;Add RETURNING when possible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inserting in loop&lt;/td&gt;
&lt;td&gt;Slow performance, high latency&lt;/td&gt;
&lt;td&gt;Use multi-row or COPY&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  8. Real-World Project Example: E-Commerce Product Import
&lt;/h3&gt;

&lt;p&gt;Imagine you receive a CSV file from your supplier with 5,000 new products.&lt;br&gt;&lt;br&gt;
Instead of looping 5,000 times:&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="c1"&gt;-- PostgreSQL efficient bulk import (Day 5 level)&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="s1"&gt;'/path/to/products.csv'&lt;/span&gt;
&lt;span class="k"&gt;DELIMITER&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;
&lt;span class="n"&gt;CSV&lt;/span&gt; &lt;span class="n"&gt;HEADER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then query the newly imported rows using &lt;code&gt;RETURNING&lt;/code&gt; or a timestamp filter.&lt;/p&gt;

&lt;p&gt;This pattern is used by Shopify, Amazon, and every serious e-commerce platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;You now understand not just &lt;em&gt;how&lt;/em&gt; to insert data, but &lt;em&gt;why&lt;/em&gt; certain patterns matter in production systems. The combination of explicit column lists, multi-row inserts, and the &lt;code&gt;RETURNING&lt;/code&gt; clause gives you both safety and speed — the hallmarks of professional database engineering.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Always specify column names in &lt;code&gt;INSERT&lt;/code&gt; statements.&lt;/li&gt;
&lt;li&gt;Prefer multi-row &lt;code&gt;VALUES&lt;/code&gt; for performance.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;RETURNING&lt;/code&gt; (PostgreSQL) to eliminate extra queries.&lt;/li&gt;
&lt;li&gt;Validate early, insert atomically, and monitor with &lt;code&gt;EXPLAIN&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Master these fundamentals before moving to advanced topics like triggers or stored procedures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You have completed Day 5. Your database now has data — the foundation for every query, join, and report you will build in the coming days.&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%2Fo7tq42r0b409qbfh3icd.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%2Fo7tq42r0b409qbfh3icd.png" alt="SQL insert and returning cheat sheet" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
    </item>
    <item>
      <title>Day 4: Creating Tables – Data Types, NULL, and DEFAULT Constraints</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Sun, 24 May 2026 02:46:06 +0000</pubDate>
      <link>https://dev.to/code_2/day-4-creating-tables-data-types-null-and-default-constraints-feb</link>
      <guid>https://dev.to/code_2/day-4-creating-tables-data-types-null-and-default-constraints-feb</guid>
      <description>&lt;h2&gt;
  
  
  The Foundation of Every Relational Database: Why Table Creation Matters
&lt;/h2&gt;

&lt;p&gt;When you build any production application—whether it is a customer management system, an inventory tracker, or a full-scale e-commerce platform—the &lt;strong&gt;table&lt;/strong&gt; becomes the core structural unit that holds your data. A &lt;strong&gt;table&lt;/strong&gt; in a &lt;strong&gt;relational database&lt;/strong&gt; is not just a spreadsheet; it is a precisely defined container that enforces rules about what data can live inside it, how that data is stored, and how the &lt;strong&gt;database engine&lt;/strong&gt; will interact with it for years to come.  &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;CREATE TABLE&lt;/strong&gt; statement is the very first place where you, as a developer or architect, make decisions that affect performance, data integrity, storage costs, query speed, and even the long-term maintainability of your entire system. Today we will explore this statement in exhaustive detail: from the underlying theory of &lt;strong&gt;data types&lt;/strong&gt; to the subtle but critical behavior of &lt;strong&gt;NULL&lt;/strong&gt; values and the practical power of &lt;strong&gt;DEFAULT&lt;/strong&gt; constraints. We will examine real engineering trade-offs, internal database workflows, and the exact syntax you will use in both &lt;strong&gt;PostgreSQL&lt;/strong&gt; and &lt;strong&gt;MySQL&lt;/strong&gt;—the two databases you set up on Day 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CREATE TABLE Statement: Syntax, Structure, and Execution Flow
&lt;/h2&gt;

&lt;p&gt;At its core, the &lt;strong&gt;CREATE TABLE&lt;/strong&gt; command instructs the &lt;strong&gt;database management system&lt;/strong&gt; to allocate storage space, define column metadata, and register the table within the database’s system catalog. The engine parses your statement, validates data-type compatibility, applies any immediate constraints, and then creates the physical files (or pages) that will eventually hold rows.&lt;/p&gt;

&lt;p&gt;The basic structure looks 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;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;column_name1&lt;/span&gt; &lt;span class="n"&gt;data_type&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;column_name2&lt;/span&gt; &lt;span class="n"&gt;data_type&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;constraints&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;Every column definition consists of three mandatory parts and one optional but extremely important part:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;column name&lt;/strong&gt; (must be unique within the table)&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;data type&lt;/strong&gt; (determines storage format, range, and behavior)&lt;/li&gt;
&lt;li&gt;Optional &lt;strong&gt;constraints&lt;/strong&gt; such as &lt;strong&gt;NOT NULL&lt;/strong&gt; or &lt;strong&gt;DEFAULT&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the &lt;strong&gt;database engine&lt;/strong&gt; processes this statement, it performs several internal steps in sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Acquires a schema lock to prevent concurrent modifications.&lt;/li&gt;
&lt;li&gt;Validates that the chosen &lt;strong&gt;data types&lt;/strong&gt; exist and are compatible with the storage engine.&lt;/li&gt;
&lt;li&gt;Allocates space in the &lt;strong&gt;heap&lt;/strong&gt; (the main table storage area).&lt;/li&gt;
&lt;li&gt;Records the table definition in the system catalog tables (pg_class and pg_attribute in &lt;strong&gt;PostgreSQL&lt;/strong&gt;, or information_schema.columns in both engines).&lt;/li&gt;
&lt;li&gt;If the table is created successfully, it becomes immediately queryable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Choosing the wrong &lt;strong&gt;data type&lt;/strong&gt; or forgetting a &lt;strong&gt;constraint&lt;/strong&gt; at this stage can force you to run expensive &lt;strong&gt;ALTER TABLE&lt;/strong&gt; operations later—which lock the table and can cause downtime in high-traffic systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Types: The Language Your Database Speaks
&lt;/h2&gt;

&lt;p&gt;Every value you store must be declared with an explicit &lt;strong&gt;data type&lt;/strong&gt;. The &lt;strong&gt;database engine&lt;/strong&gt; uses this declaration to decide how much disk space to reserve, how to encode the value in memory, how to compare values during queries, and how to index the column efficiently. Selecting the correct &lt;strong&gt;data type&lt;/strong&gt; is both an art and a science; it directly impacts storage costs, query performance, and application correctness.&lt;/p&gt;

&lt;h3&gt;
  
  
  Numeric Data Types
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Integer&lt;/strong&gt; types are the workhorses of most applications. In &lt;strong&gt;PostgreSQL&lt;/strong&gt; you have &lt;strong&gt;SMALLINT&lt;/strong&gt; (2 bytes, ±32,767), &lt;strong&gt;INTEGER&lt;/strong&gt; (4 bytes, ±2.1 billion), and &lt;strong&gt;BIGINT&lt;/strong&gt; (8 bytes, ±9 quintillion). &lt;strong&gt;MySQL&lt;/strong&gt; offers the nearly identical &lt;strong&gt;TINYINT&lt;/strong&gt;, &lt;strong&gt;SMALLINT&lt;/strong&gt;, &lt;strong&gt;MEDIUMINT&lt;/strong&gt;, &lt;strong&gt;INT&lt;/strong&gt;, and &lt;strong&gt;BIGINT&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;For fractional numbers, use &lt;strong&gt;NUMERIC(precision, scale)&lt;/strong&gt; (also called &lt;strong&gt;DECIMAL&lt;/strong&gt; in &lt;strong&gt;MySQL&lt;/strong&gt;). This type stores exact decimal values—critical for financial data—unlike &lt;strong&gt;REAL&lt;/strong&gt; or &lt;strong&gt;DOUBLE PRECISION&lt;/strong&gt;, which use floating-point approximation and can introduce rounding errors that accumulate over millions of transactions.&lt;/p&gt;

&lt;p&gt;Real-world example: an order total column should never use &lt;strong&gt;DOUBLE PRECISION&lt;/strong&gt;; always use &lt;strong&gt;NUMERIC(12,2)&lt;/strong&gt; to guarantee penny-level accuracy across years of compounding calculations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Character Data Types
&lt;/h3&gt;

&lt;p&gt;Text storage comes in two families. &lt;strong&gt;VARCHAR(n)&lt;/strong&gt; stores variable-length strings up to n characters and is the default choice in modern applications. &lt;strong&gt;TEXT&lt;/strong&gt; (or &lt;strong&gt;LONGTEXT&lt;/strong&gt; in &lt;strong&gt;MySQL&lt;/strong&gt;) removes the length limit entirely and is ideal for product descriptions or user comments.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CHAR(n)&lt;/strong&gt; is fixed-length and right-pads with spaces; it can be slightly faster for very short, consistently sized fields (e.g., country codes), but it wastes space otherwise. In high-scale systems, the performance difference between &lt;strong&gt;VARCHAR&lt;/strong&gt; and &lt;strong&gt;TEXT&lt;/strong&gt; is negligible because both are stored out-of-line when they grow large, but the choice still matters for index size and memory usage during sorting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Date and Time Data Types
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;DATE&lt;/strong&gt;, &lt;strong&gt;TIME&lt;/strong&gt;, &lt;strong&gt;TIMESTAMP&lt;/strong&gt;, and &lt;strong&gt;TIMESTAMPTZ&lt;/strong&gt; (timestamp with time zone in &lt;strong&gt;PostgreSQL&lt;/strong&gt;) are essential. &lt;strong&gt;PostgreSQL&lt;/strong&gt;’s &lt;strong&gt;TIMESTAMPTZ&lt;/strong&gt; automatically normalizes everything to UTC internally while preserving the original time zone for display—an architectural decision that prevents daylight-saving bugs that plague many legacy &lt;strong&gt;MySQL&lt;/strong&gt; applications using plain &lt;strong&gt;DATETIME&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Always store timestamps with time zone awareness unless your entire system operates in a single fixed timezone. The internal workflow is simple: the engine converts the input to UTC on write and converts back on read based on the client’s session timezone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boolean and Specialized Types
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;BOOLEAN&lt;/strong&gt; type (or &lt;strong&gt;BOOL&lt;/strong&gt;) stores true, false, or &lt;strong&gt;NULL&lt;/strong&gt;. It occupies only one byte yet saves you from the classic “0/1 magic number” anti-pattern that leads to bugs when someone later interprets 2 as “maybe.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt; also offers &lt;strong&gt;JSONB&lt;/strong&gt; for semi-structured data and &lt;strong&gt;UUID&lt;/strong&gt; for globally unique identifiers—both of which we will use in production examples later in the series.&lt;/p&gt;

&lt;h2&gt;
  
  
  NULL: The Concept of “Value Unknown”
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;NULL&lt;/strong&gt; is not a value; it is the explicit absence of a value. The &lt;strong&gt;SQL standard&lt;/strong&gt; treats &lt;strong&gt;NULL&lt;/strong&gt; through &lt;strong&gt;three-valued logic&lt;/strong&gt; (true, false, unknown). This means that any comparison involving &lt;strong&gt;NULL&lt;/strong&gt;—even &lt;code&gt;NULL = NULL&lt;/code&gt;—evaluates to unknown, not true.  &lt;/p&gt;

&lt;p&gt;From an architectural standpoint, the &lt;strong&gt;database engine&lt;/strong&gt; stores a special null bitmap for each row. When a column is &lt;strong&gt;NULL&lt;/strong&gt;, the engine skips storing any data for that column, saving space. However, this bitmap adds a tiny overhead to every row, which becomes measurable only at billions of rows.&lt;/p&gt;

&lt;p&gt;In real systems, &lt;strong&gt;NULL&lt;/strong&gt; represents legitimate business states: “user has not yet set a middle name,” “order has not yet shipped,” or “product has no discount expiration date.” Misusing &lt;strong&gt;NULL&lt;/strong&gt; for “zero” or “empty string” is one of the most common sources of incorrect analytics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enforcing Presence with NOT NULL Constraints
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;NOT NULL&lt;/strong&gt; constraint tells the &lt;strong&gt;database engine&lt;/strong&gt; to reject any &lt;strong&gt;INSERT&lt;/strong&gt; or &lt;strong&gt;UPDATE&lt;/strong&gt; that would leave the column without a value. This is enforced at write time, before the row reaches disk.  &lt;/p&gt;

&lt;p&gt;Placing &lt;strong&gt;NOT NULL&lt;/strong&gt; on columns that your application logic depends on (email, created_at, status) prevents entire classes of runtime errors. It also allows the query planner to generate more efficient execution plans because the engine knows the column will never be unknown.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supplying Sensible Defaults with the DEFAULT Constraint
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;DEFAULT&lt;/strong&gt; constraint provides an automatic value when none is supplied during an &lt;strong&gt;INSERT&lt;/strong&gt;. The engine evaluates the default expression at write time and substitutes it seamlessly.  &lt;/p&gt;

&lt;p&gt;Common realistic defaults include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CURRENT_TIMESTAMP&lt;/code&gt; or &lt;code&gt;NOW()&lt;/code&gt; for audit columns&lt;/li&gt;
&lt;li&gt;A literal string such as &lt;code&gt;'active'&lt;/code&gt; for status columns&lt;/li&gt;
&lt;li&gt;A numeric literal such as &lt;code&gt;0.00&lt;/code&gt; for price fields&lt;/li&gt;
&lt;li&gt;A complex expression such as &lt;code&gt;gen_random_uuid()&lt;/code&gt; in &lt;strong&gt;PostgreSQL&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;MySQL&lt;/strong&gt; and &lt;strong&gt;PostgreSQL&lt;/strong&gt; both support &lt;strong&gt;DEFAULT&lt;/strong&gt; on almost every data type, but &lt;strong&gt;PostgreSQL&lt;/strong&gt; allows far richer expressions (including subqueries and functions) because its parser is more expressive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Production-Grade Table: A Complete Realistic Example
&lt;/h2&gt;

&lt;p&gt;Let us create a &lt;strong&gt;users&lt;/strong&gt; table that reflects real engineering decisions made every day in SaaS companies.&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="c1"&gt;-- PostgreSQL version&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;              &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;GENERATED&lt;/span&gt; &lt;span class="n"&gt;ALWAYS&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;IDENTITY&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;           &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;       &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;        &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;          &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'pending'&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt;      &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt;  &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;last_login_at&lt;/span&gt;   &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;preferences&lt;/span&gt;     &lt;span class="n"&gt;JSONB&lt;/span&gt;        &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'{}'&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JSONB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;is_verified&lt;/span&gt;     &lt;span class="nb"&gt;BOOLEAN&lt;/span&gt;      &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;FALSE&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Equivalent MySQL version (note AUTO_INCREMENT and slight syntax differences)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;              &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;           &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;       &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;        &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;          &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'pending'&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt;      &lt;span class="nb"&gt;DATETIME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;last_login_at&lt;/span&gt;   &lt;span class="nb"&gt;DATETIME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;preferences&lt;/span&gt;     &lt;span class="n"&gt;JSON&lt;/span&gt;         &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JSON_OBJECT&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;is_verified&lt;/span&gt;     &lt;span class="nb"&gt;TINYINT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ENGINE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;InnoDB&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;CHARSET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;utf8mb4&lt;/span&gt; &lt;span class="k"&gt;COLLATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;utf8mb4_unicode_ci&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Walk through the logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;id&lt;/strong&gt; uses an auto-incrementing or identity column so the engine guarantees uniqueness without application-level coordination.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;email&lt;/strong&gt; is &lt;strong&gt;NOT NULL&lt;/strong&gt; because every user must have one; the &lt;strong&gt;database engine&lt;/strong&gt; will reject any attempt to create a row without it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;status&lt;/strong&gt; has a &lt;strong&gt;DEFAULT&lt;/strong&gt; so new users start in a safe pending state even if the application forgets to specify it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;created_at&lt;/strong&gt; defaults to the exact moment of insertion, providing a reliable audit trail without requiring application code to remember to set it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;preferences&lt;/strong&gt; as &lt;strong&gt;JSONB&lt;/strong&gt; (PostgreSQL) or &lt;strong&gt;JSON&lt;/strong&gt; (MySQL) allows flexible storage of user settings without schema changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you execute this statement, the &lt;strong&gt;database engine&lt;/strong&gt; creates the table, builds the internal row header with the null bitmap, reserves space for the default values, and registers the column metadata so future queries can leverage type information for optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Engineering Trade-offs, Performance Implications, and Best Practices
&lt;/h2&gt;

&lt;p&gt;Choosing &lt;strong&gt;data types&lt;/strong&gt; and constraints is never free.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wider numeric types (&lt;strong&gt;BIGINT&lt;/strong&gt; vs &lt;strong&gt;INTEGER&lt;/strong&gt;) double storage and index size but prevent overflow bugs that crash production systems.
&lt;/li&gt;
&lt;li&gt;Variable-length types (&lt;strong&gt;VARCHAR&lt;/strong&gt;, &lt;strong&gt;TEXT&lt;/strong&gt;) are more space-efficient but require an extra length prefix and can fragment pages over time.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NOT NULL&lt;/strong&gt; columns allow the query planner to skip null-check branches, improving index usage and reducing CPU cycles.
&lt;/li&gt;
&lt;li&gt;Over-use of &lt;strong&gt;DEFAULT&lt;/strong&gt; expressions that call functions (e.g., &lt;code&gt;NOW()&lt;/code&gt;) adds microseconds per row; in a table receiving 10,000 inserts per second, this becomes measurable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Best practice: declare the narrowest, most restrictive &lt;strong&gt;data type&lt;/strong&gt; and the strictest &lt;strong&gt;constraints&lt;/strong&gt; that still match real business rules. Run &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; on representative queries after creation to validate that the engine is using the types and constraints you intended. In high-scale environments, these early decisions determine whether your database stays on a single node or needs sharding later.&lt;/p&gt;

&lt;p&gt;For teams working in both &lt;strong&gt;PostgreSQL&lt;/strong&gt; and &lt;strong&gt;MySQL&lt;/strong&gt;, maintain separate migration scripts or use an abstraction layer that understands the subtle syntax differences—especially around default timestamps and identity columns.&lt;/p&gt;

&lt;p&gt;If you want to take these concepts from theory to production-grade mastery with dozens of additional exercises, real schema evolution patterns, and battle-tested migration strategies, grab the comprehensive &lt;strong&gt;SQL Playbook&lt;/strong&gt; at &lt;a href="https://codewithdhanian.gumroad.com/l/hjmix" rel="noopener noreferrer"&gt;https://codewithdhanian.gumroad.com/l/hjmix&lt;/a&gt; —it was built exactly for engineers who want to move beyond tutorials and ship reliable systems.&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%2F852lmmfrwuxf6hla2dj1.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%2F852lmmfrwuxf6hla2dj1.png" alt="Creating SQL tables: data types and constraints" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
    </item>
    <item>
      <title>Day 3: Creating and Dropping Databases – CREATE DATABASE, DROP DATABASE</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Sat, 23 May 2026 12:38:47 +0000</pubDate>
      <link>https://dev.to/code_2/day-3-creating-and-dropping-databases-create-database-drop-database-3kdk</link>
      <guid>https://dev.to/code_2/day-3-creating-and-dropping-databases-create-database-drop-database-3kdk</guid>
      <description>&lt;p&gt;Creating a &lt;strong&gt;database&lt;/strong&gt; is one of the most fundamental operations you will perform as a SQL developer or database engineer. It marks the moment you move from simply connecting to a &lt;strong&gt;database management system&lt;/strong&gt; to actually owning and organizing your own structured data environment. In this tutorial, we will explore exactly how &lt;strong&gt;databases&lt;/strong&gt; are created and removed, why these operations behave the way they do under the hood, and how to handle them responsibly in both development and production environments.&lt;/p&gt;

&lt;p&gt;We will work with the two most popular open-source &lt;strong&gt;relational database management systems&lt;/strong&gt; introduced earlier: &lt;strong&gt;PostgreSQL&lt;/strong&gt; and &lt;strong&gt;MySQL&lt;/strong&gt;. Although both support the core SQL commands &lt;strong&gt;CREATE DATABASE&lt;/strong&gt; and &lt;strong&gt;DROP DATABASE&lt;/strong&gt;, their implementations differ in important architectural ways that affect performance, security, and scalability.&lt;/p&gt;

&lt;h3&gt;
  
  
  What a Database Actually Represents
&lt;/h3&gt;

&lt;p&gt;Before writing any code, it is essential to understand what a &lt;strong&gt;database&lt;/strong&gt; truly is from an architectural perspective. In a &lt;strong&gt;relational database management system&lt;/strong&gt;, a &lt;strong&gt;database&lt;/strong&gt; is a named container that holds multiple &lt;strong&gt;schemas&lt;/strong&gt;, &lt;strong&gt;tables&lt;/strong&gt;, &lt;strong&gt;indexes&lt;/strong&gt;, &lt;strong&gt;views&lt;/strong&gt;, &lt;strong&gt;functions&lt;/strong&gt;, and other database objects. It acts as a logical boundary for data isolation, access control, and resource allocation.&lt;/p&gt;

&lt;p&gt;Physically, a &lt;strong&gt;database&lt;/strong&gt; is more than just a name. In &lt;strong&gt;PostgreSQL&lt;/strong&gt;, each &lt;strong&gt;database&lt;/strong&gt; corresponds to a separate set of files on disk, managed by the &lt;strong&gt;postmaster&lt;/strong&gt; process. These files store the actual data pages, transaction logs (&lt;strong&gt;WAL&lt;/strong&gt;), and catalog metadata. In &lt;strong&gt;MySQL&lt;/strong&gt; (using the default &lt;strong&gt;InnoDB&lt;/strong&gt; storage engine), each &lt;strong&gt;database&lt;/strong&gt; typically maps to a subdirectory under the MySQL data directory, with table definitions and data stored in &lt;code&gt;.frm&lt;/code&gt;, &lt;code&gt;.ibd&lt;/code&gt;, or similar files depending on the engine.&lt;/p&gt;

&lt;p&gt;This separation is deliberate. It allows a single &lt;strong&gt;database server&lt;/strong&gt; instance to host dozens or even hundreds of independent &lt;strong&gt;databases&lt;/strong&gt;, each with its own security context and performance characteristics. This architecture is what enables multi-tenant applications, separate development/staging/production environments, and efficient resource isolation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The CREATE DATABASE Statement
&lt;/h3&gt;

&lt;p&gt;The primary command to create a new &lt;strong&gt;database&lt;/strong&gt; is &lt;strong&gt;CREATE DATABASE&lt;/strong&gt;. The basic syntax is intentionally simple, yet the optional clauses reveal deep control over how the &lt;strong&gt;database&lt;/strong&gt; will behave.&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="c1"&gt;-- PostgreSQL version&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;my_app_production&lt;/span&gt;
    &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="k"&gt;OWNER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;postgres&lt;/span&gt;
         &lt;span class="k"&gt;ENCODING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'UTF8'&lt;/span&gt;
         &lt;span class="n"&gt;LC_COLLATE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'en_US.UTF-8'&lt;/span&gt;
         &lt;span class="n"&gt;LC_CTYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'en_US.UTF-8'&lt;/span&gt;
         &lt;span class="k"&gt;TEMPLATE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;template0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- MySQL version&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;my_app_production&lt;/span&gt;
    &lt;span class="nb"&gt;CHARACTER&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;utf8mb4&lt;/span&gt;
    &lt;span class="k"&gt;COLLATE&lt;/span&gt; &lt;span class="n"&gt;utf8mb4_unicode_ci&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let us break down every important part of these statements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WITH&lt;/strong&gt; (PostgreSQL only): Introduces a list of optional parameters that configure the new &lt;strong&gt;database&lt;/strong&gt; at creation time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OWNER&lt;/strong&gt;: Specifies which &lt;strong&gt;role&lt;/strong&gt; (user) will own the &lt;strong&gt;database&lt;/strong&gt;. The owner has full rights to create objects, grant privileges, and drop the &lt;strong&gt;database&lt;/strong&gt; later. In production systems, it is a best practice to create a dedicated application &lt;strong&gt;role&lt;/strong&gt; with the least privileges necessary rather than using the default superuser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ENCODING&lt;/strong&gt; / &lt;strong&gt;CHARACTER SET&lt;/strong&gt;: Defines how text data will be stored. &lt;strong&gt;UTF8&lt;/strong&gt; (PostgreSQL) or &lt;strong&gt;utf8mb4&lt;/strong&gt; (MySQL) is almost always the correct choice today because it properly supports international characters, emojis, and modern languages without data corruption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LC_COLLATE&lt;/strong&gt; and &lt;strong&gt;LC_CTYPE&lt;/strong&gt;: Control how string sorting and character classification work. These settings affect query performance on text columns and the results of &lt;strong&gt;ORDER BY&lt;/strong&gt; operations. Choosing the wrong collation can lead to unexpected sorting behavior or degraded index performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TEMPLATE&lt;/strong&gt; (PostgreSQL): Every new &lt;strong&gt;database&lt;/strong&gt; is cloned from a template. The default &lt;strong&gt;template1&lt;/strong&gt; includes standard objects and extensions. Using &lt;strong&gt;template0&lt;/strong&gt; gives you a completely clean slate, which is preferable when you want strict control over what exists in the new &lt;strong&gt;database&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;strong&gt;MySQL&lt;/strong&gt;, the equivalent parameters are simpler because &lt;strong&gt;MySQL&lt;/strong&gt; handles character sets at both the server and &lt;strong&gt;database&lt;/strong&gt; level. The &lt;strong&gt;COLLATE&lt;/strong&gt; clause determines the default sorting and comparison rules for all tables created inside that &lt;strong&gt;database&lt;/strong&gt; unless overridden at the table or column level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why These Options Matter in Real Engineering
&lt;/h3&gt;

&lt;p&gt;Choosing the right &lt;strong&gt;encoding&lt;/strong&gt; and &lt;strong&gt;collation&lt;/strong&gt; at creation time is not a cosmetic decision. Once a &lt;strong&gt;database&lt;/strong&gt; is created, changing these properties is extremely difficult and often requires a full data export/import cycle. In large-scale systems, incorrect collation choices have caused production incidents where searches and sorts returned inconsistent results across environments.&lt;/p&gt;

&lt;p&gt;Performance implications are also significant. A &lt;strong&gt;database&lt;/strong&gt; with the wrong &lt;strong&gt;collation&lt;/strong&gt; can prevent the query planner from using indexes efficiently during text comparisons, leading to full table scans even when indexes exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Databases in Practice: Development Workflows
&lt;/h3&gt;

&lt;p&gt;Professional developers rarely create &lt;strong&gt;databases&lt;/strong&gt; manually in production. Instead, they follow repeatable workflows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use infrastructure-as-code tools or migration scripts.&lt;/li&gt;
&lt;li&gt;Create separate &lt;strong&gt;databases&lt;/strong&gt; for development, testing, and production.&lt;/li&gt;
&lt;li&gt;Automate creation as part of CI/CD pipelines so every developer works with identical starting conditions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is a realistic example of a script you might keep in your project repository:&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="c1"&gt;-- create_dev_db.sql&lt;/span&gt;
&lt;span class="k"&gt;DO&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
    &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;pg_database&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;datname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'my_app_dev'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
        &lt;span class="n"&gt;PERFORM&lt;/span&gt; &lt;span class="n"&gt;dblink_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'host=localhost user=postgres'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'CREATE DATABASE my_app_dev WITH OWNER = app_user ENCODING = &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;UTF8&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern uses a conditional check to make the script idempotent, meaning it can be run multiple times without error.&lt;/p&gt;

&lt;h3&gt;
  
  
  The DROP DATABASE Statement
&lt;/h3&gt;

&lt;p&gt;Removing a &lt;strong&gt;database&lt;/strong&gt; is the counterpart to creation and must be treated with respect. The syntax is:&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="c1"&gt;-- PostgreSQL&lt;/span&gt;
&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;my_app_production&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Safer version&lt;/span&gt;
&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;my_app_production&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- MySQL&lt;/span&gt;
&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;my_app_production&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;my_app_production&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;IF EXISTS&lt;/strong&gt; clause prevents an error if the &lt;strong&gt;database&lt;/strong&gt; does not exist. This is especially valuable in automated scripts.&lt;/p&gt;

&lt;p&gt;Important behavior differences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In &lt;strong&gt;PostgreSQL&lt;/strong&gt;, you cannot drop a &lt;strong&gt;database&lt;/strong&gt; while active connections exist. The server will reject the command unless you use the &lt;strong&gt;WITH FORCE&lt;/strong&gt; option (available in newer versions) or first terminate connections manually.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;MySQL&lt;/strong&gt;, dropping a &lt;strong&gt;database&lt;/strong&gt; is more permissive but still requires appropriate privileges.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DROP DATABASE&lt;/strong&gt; is a permanent, non-recoverable operation in most cases. The files on disk are removed, and all data disappears. This is why production systems almost never allow direct &lt;strong&gt;DROP DATABASE&lt;/strong&gt; commands except during controlled maintenance windows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal Workflows and System Behavior
&lt;/h3&gt;

&lt;p&gt;When you execute &lt;strong&gt;CREATE DATABASE&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;database server&lt;/strong&gt; validates your permissions.&lt;/li&gt;
&lt;li&gt;It allocates a new &lt;strong&gt;database OID&lt;/strong&gt; (object identifier).&lt;/li&gt;
&lt;li&gt;It copies the template files (PostgreSQL) or creates a new subdirectory (MySQL).&lt;/li&gt;
&lt;li&gt;It updates the system catalogs (&lt;strong&gt;pg_database&lt;/strong&gt; in PostgreSQL, &lt;strong&gt;mysql&lt;/strong&gt; system database in MySQL).&lt;/li&gt;
&lt;li&gt;It initializes the default &lt;strong&gt;schema&lt;/strong&gt; (public in PostgreSQL, the database itself in MySQL).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you execute &lt;strong&gt;DROP DATABASE&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The server checks for active connections and may block or terminate them.&lt;/li&gt;
&lt;li&gt;It removes all associated files from the filesystem.&lt;/li&gt;
&lt;li&gt;It cleans up metadata entries across system catalogs.&lt;/li&gt;
&lt;li&gt;Any open transactions involving that &lt;strong&gt;database&lt;/strong&gt; are rolled back or invalidated.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These operations affect the entire server instance. On very large systems, creating or dropping &lt;strong&gt;databases&lt;/strong&gt; can momentarily increase I/O load because of file system operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices and Scalability Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Never create &lt;strong&gt;databases&lt;/strong&gt; with generic names like "test" or "db1" in production. Use descriptive, versioned names that reflect purpose and environment.&lt;/li&gt;
&lt;li&gt;Prefer &lt;strong&gt;schemas&lt;/strong&gt; over multiple &lt;strong&gt;databases&lt;/strong&gt; when you need logical separation within the same data set. This is more efficient because it avoids the overhead of managing separate file sets.&lt;/li&gt;
&lt;li&gt;In multi-tenant SaaS applications, some teams create one &lt;strong&gt;database&lt;/strong&gt; per customer for strong isolation, while others use a single &lt;strong&gt;database&lt;/strong&gt; with tenant_id columns. Each approach has different scalability and backup implications.&lt;/li&gt;
&lt;li&gt;Always back up critical &lt;strong&gt;databases&lt;/strong&gt; before any &lt;strong&gt;DROP&lt;/strong&gt; operation.&lt;/li&gt;
&lt;li&gt;Grant the minimal privileges necessary. Application users should rarely have &lt;strong&gt;CREATE DATABASE&lt;/strong&gt; or &lt;strong&gt;DROP DATABASE&lt;/strong&gt; rights.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real-World Engineering Example
&lt;/h3&gt;

&lt;p&gt;Imagine you are building an e-commerce platform. You might maintain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ecommerce_production&lt;/code&gt; – live customer data&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ecommerce_staging&lt;/code&gt; – pre-production testing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ecommerce_dev&lt;/code&gt; – local development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You would create these using scripts that also initialize required extensions, default roles, and security policies. When a new feature requires schema changes that cannot be rolled back easily, you create a fresh &lt;strong&gt;database&lt;/strong&gt; from a recent backup of production, test the migration thoroughly, then promote the change.&lt;/p&gt;

&lt;p&gt;These patterns ensure consistency, reduce human error, and make your infrastructure reproducible.&lt;/p&gt;

&lt;p&gt;For even more in-depth examples and exercises, consider purchasing this SQL Playbook: &lt;a href="https://codewithdhanian.gumroad.com/l/hjmix" rel="noopener noreferrer"&gt;https://codewithdhanian.gumroad.com/l/hjmix&lt;/a&gt;&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%2Fm4gscte0x3bjbvmbi0st.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%2Fm4gscte0x3bjbvmbi0st.png" alt="Day 3: Creating and Dropping Databases" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
    </item>
    <item>
      <title>Day 2: Installing PostgreSQL/MySQL and Setting Up Your First Database</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Sat, 23 May 2026 12:16:57 +0000</pubDate>
      <link>https://dev.to/code_2/day-2-installing-postgresqlmysql-and-setting-up-your-first-database-1mm8</link>
      <guid>https://dev.to/code_2/day-2-installing-postgresqlmysql-and-setting-up-your-first-database-1mm8</guid>
      <description>&lt;p&gt;In database development, the quality of your local environment directly determines how effectively you will learn and how reliably you will build production systems later. Today we focus entirely on installing &lt;strong&gt;PostgreSQL&lt;/strong&gt; and &lt;strong&gt;MySQL&lt;/strong&gt;, understanding the &lt;strong&gt;client-server architecture&lt;/strong&gt; that powers them, and creating your first functional &lt;strong&gt;database&lt;/strong&gt;. We will examine every step from a professional engineering perspective so you can make informed decisions whether you are a complete beginner or an experienced developer setting up a new machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Client-Server Architecture Behind Every Relational Database
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;relational database management system&lt;/strong&gt; (&lt;strong&gt;RDBMS&lt;/strong&gt;) is never just a file on your computer. It follows a strict &lt;strong&gt;client-server model&lt;/strong&gt;. The &lt;strong&gt;database server&lt;/strong&gt; is a background process (daemon) that runs continuously, manages data files on disk, enforces &lt;strong&gt;referential integrity&lt;/strong&gt;, handles concurrent connections, and executes &lt;strong&gt;SQL&lt;/strong&gt; statements. The &lt;strong&gt;client&lt;/strong&gt; is any tool or application that connects to this server over the network or locally via a socket.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt; and &lt;strong&gt;MySQL&lt;/strong&gt; both implement this architecture, but they differ in design philosophy. &lt;strong&gt;PostgreSQL&lt;/strong&gt; is a fully &lt;strong&gt;object-relational&lt;/strong&gt; system with strong emphasis on standards compliance, extensibility, and advanced features such as &lt;strong&gt;JSONB&lt;/strong&gt; support and custom data types. &lt;strong&gt;MySQL&lt;/strong&gt; is optimized for read-heavy web workloads and remains the default choice for many content-driven applications due to its speed and widespread ecosystem support.&lt;/p&gt;

&lt;p&gt;When the server starts, it listens on a specific &lt;strong&gt;TCP port&lt;/strong&gt;: &lt;strong&gt;5432&lt;/strong&gt; for &lt;strong&gt;PostgreSQL&lt;/strong&gt; and &lt;strong&gt;3306&lt;/strong&gt; for &lt;strong&gt;MySQL&lt;/strong&gt;. Clients connect using these ports, authenticate with a username and password, and then send &lt;strong&gt;SQL&lt;/strong&gt; commands. The server parses the query, checks permissions, optimizes the execution plan using its internal &lt;strong&gt;query planner&lt;/strong&gt;, and returns results. Understanding this flow helps you debug connection issues later and appreciate why proper installation and configuration matter for both development speed and long-term scalability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing Between PostgreSQL and MySQL
&lt;/h2&gt;

&lt;p&gt;Both systems are excellent open-source &lt;strong&gt;RDBMS&lt;/strong&gt; options, but they serve slightly different needs. &lt;strong&gt;PostgreSQL&lt;/strong&gt; excels in complex queries, &lt;strong&gt;window functions&lt;/strong&gt;, full &lt;strong&gt;ACID&lt;/strong&gt; compliance out of the box, and handling large analytical workloads. &lt;strong&gt;MySQL&lt;/strong&gt; is often lighter on resources and has tighter integration with popular web stacks such as PHP and certain cloud platforms. Many professional developers install both so they can work on different projects without friction. We will cover the complete installation process for each.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing PostgreSQL
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation on Major Operating Systems
&lt;/h3&gt;

&lt;p&gt;The installation process places the &lt;strong&gt;PostgreSQL&lt;/strong&gt; server binaries, client tools, and default data directory on your system.&lt;/p&gt;

&lt;p&gt;On &lt;strong&gt;macOS&lt;/strong&gt;, the recommended developer approach uses &lt;strong&gt;Homebrew&lt;/strong&gt;. Open your 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;brew &lt;span class="nb"&gt;install &lt;/span&gt;postgresql
brew services start postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command installs the latest stable version, creates the necessary directories, and registers &lt;strong&gt;PostgreSQL&lt;/strong&gt; as a background service that starts automatically.&lt;/p&gt;

&lt;p&gt;On &lt;strong&gt;Ubuntu/Debian Linux&lt;/strong&gt;, use the package manager:&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;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;postgresql postgresql-contrib
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On &lt;strong&gt;Windows&lt;/strong&gt;, download the official EnterpriseDB installer from the &lt;strong&gt;PostgreSQL&lt;/strong&gt; website and follow the wizard. Choose the default port &lt;strong&gt;5432&lt;/strong&gt; and remember the password you set for the &lt;strong&gt;postgres&lt;/strong&gt; superuser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Post-Installation Verification and Initialization
&lt;/h3&gt;

&lt;p&gt;After installation, &lt;strong&gt;PostgreSQL&lt;/strong&gt; runs an initialization process called &lt;strong&gt;initdb&lt;/strong&gt; (automatically handled by the installer or package manager). This creates the &lt;strong&gt;data directory&lt;/strong&gt; (often &lt;code&gt;/var/lib/postgresql/data&lt;/code&gt; on Linux or &lt;code&gt;~/Library/Application Support/Postgres&lt;/code&gt; on macOS) containing the system catalogs, template databases, and configuration files.&lt;/p&gt;

&lt;p&gt;Verify everything is running by checking the service status or using the client tool:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This confirms the &lt;strong&gt;psql&lt;/strong&gt; command-line client is available and in your &lt;strong&gt;PATH&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Switch to the default &lt;strong&gt;postgres&lt;/strong&gt; user (on Linux/macOS) or open &lt;strong&gt;pgAdmin&lt;/strong&gt; on Windows to continue setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Your First PostgreSQL Database
&lt;/h2&gt;

&lt;p&gt;Create a dedicated database and user instead of using the default &lt;strong&gt;postgres&lt;/strong&gt; superuser for daily work. This follows security best practices and prevents accidental destructive commands.&lt;/p&gt;

&lt;p&gt;First, create a new user account:&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;CREATE&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="n"&gt;myappuser&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;PASSWORD&lt;/span&gt; &lt;span class="s1"&gt;'strong_password_here'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create the actual database:&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;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;myfirstdb&lt;/span&gt; &lt;span class="k"&gt;OWNER&lt;/span&gt; &lt;span class="n"&gt;myappuser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grant necessary privileges:&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;GRANT&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;myfirstdb&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;myappuser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect to your new database using the &lt;strong&gt;psql&lt;/strong&gt; client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nt"&gt;-U&lt;/span&gt; myappuser &lt;span class="nt"&gt;-d&lt;/span&gt; myfirstdb &lt;span class="nt"&gt;-h&lt;/span&gt; localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-U&lt;/code&gt; flag specifies the user, &lt;code&gt;-d&lt;/code&gt; the database, and &lt;code&gt;-h localhost&lt;/code&gt; forces a TCP connection so you can see network behavior. Once inside &lt;strong&gt;psql&lt;/strong&gt;, you can run &lt;code&gt;\l&lt;/code&gt; to list databases and confirm your new database exists.&lt;/p&gt;

&lt;p&gt;For a graphical interface, install &lt;strong&gt;pgAdmin&lt;/strong&gt;. It provides a visual browser of databases, schemas, tables, and query tools while still connecting to the same underlying server. This dual workflow (command line for speed, GUI for exploration) is standard in professional development environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing MySQL
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation Approaches
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;MySQL&lt;/strong&gt; installation follows a similar client-server pattern but uses different binaries and configuration files.&lt;/p&gt;

&lt;p&gt;On &lt;strong&gt;macOS&lt;/strong&gt; with &lt;strong&gt;Homebrew&lt;/strong&gt;:&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;mysql
brew services start mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On &lt;strong&gt;Ubuntu/Debian&lt;/strong&gt;:&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;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;mysql-server
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During installation on Linux, the system creates the &lt;strong&gt;root&lt;/strong&gt; user with a temporary password that you must secure immediately using the &lt;code&gt;mysql_secure_installation&lt;/code&gt; script.&lt;/p&gt;

&lt;p&gt;On &lt;strong&gt;Windows&lt;/strong&gt;, use the official MySQL Installer and select the &lt;strong&gt;Developer Default&lt;/strong&gt; setup type.&lt;/p&gt;

&lt;h3&gt;
  
  
  MySQL Post-Installation Steps
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;MySQL&lt;/strong&gt; stores its data in a directory controlled by the &lt;strong&gt;mysqld&lt;/strong&gt; daemon. The main configuration file is &lt;code&gt;my.cnf&lt;/code&gt; (or &lt;code&gt;my.ini&lt;/code&gt; on Windows), where you can later tune buffer sizes and connection limits.&lt;/p&gt;

&lt;p&gt;Verify installation:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Secure the root user immediately and create a dedicated application user:&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;ALTER&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="s1"&gt;'root'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'strong_root_password'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="s1"&gt;'myappuser'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'strong_password_here'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;myfirstdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;myfirstdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;'myappuser'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;FLUSH&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect to your new database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql &lt;span class="nt"&gt;-u&lt;/span&gt; myappuser &lt;span class="nt"&gt;-p&lt;/span&gt; myfirstdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-p&lt;/code&gt; flag prompts for the password, keeping it out of command history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MySQL Workbench&lt;/strong&gt; serves as the official graphical client, offering schema design, query execution, and server status monitoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Production-Ready Local Setup
&lt;/h2&gt;

&lt;p&gt;Never leave default passwords or the root user exposed in development. Always create application-specific users with the minimum required privileges. On both systems, configure the server to listen only on localhost during development to reduce the attack surface.&lt;/p&gt;

&lt;p&gt;Monitor the server logs early. &lt;strong&gt;PostgreSQL&lt;/strong&gt; logs are in the data directory under &lt;code&gt;log/&lt;/code&gt;, while &lt;strong&gt;MySQL&lt;/strong&gt; uses the error log defined in the configuration file. These logs reveal connection attempts, slow queries, and authentication failures.&lt;/p&gt;

&lt;p&gt;Consider using &lt;strong&gt;Docker&lt;/strong&gt; for repeatable environments in larger projects. A simple Docker Compose setup can spin up isolated &lt;strong&gt;PostgreSQL&lt;/strong&gt; or &lt;strong&gt;MySQL&lt;/strong&gt; containers with version pinning, making your development environment identical across team members and machines.&lt;/p&gt;

&lt;p&gt;Performance implications appear even at this stage: proper data directory placement on SSDs rather than HDDs dramatically affects query speed. Memory allocation in the configuration files determines how much caching the server can perform before hitting disk.&lt;/p&gt;

&lt;p&gt;These foundational choices affect scalability later. A correctly installed and secured &lt;strong&gt;RDBMS&lt;/strong&gt; will support everything from simple prototypes to high-traffic applications without requiring major rework.&lt;/p&gt;

&lt;p&gt;If you want a complete, project-driven SQL learning experience that builds directly on these setup foundations with guided exercises and real application patterns, consider purchasing the &lt;strong&gt;SQL Playbook&lt;/strong&gt; at &lt;a href="https://codewithdhanian.gumroad.com/l/hjmix" rel="noopener noreferrer"&gt;https://codewithdhanian.gumroad.com/l/hjmix&lt;/a&gt;. It provides the structured depth many developers wish they had when starting out.&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%2Ff5gnf4let5m74getccqo.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%2Ff5gnf4let5m74getccqo.png" alt="Database installation and setup guide" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
    </item>
    <item>
      <title>Day 1: What is SQL – Databases, Tables, and Relational Concepts</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Sat, 23 May 2026 11:59:28 +0000</pubDate>
      <link>https://dev.to/code_2/day-1-what-is-sql-databases-tables-and-relational-concepts-33a1</link>
      <guid>https://dev.to/code_2/day-1-what-is-sql-databases-tables-and-relational-concepts-33a1</guid>
      <description>&lt;h2&gt;
  
  
  The Foundation of Modern Data Management
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SQL&lt;/strong&gt; stands as the universal language for interacting with relational data. Before writing a single query, it is essential to understand exactly what &lt;strong&gt;SQL&lt;/strong&gt; is, why it exists, and how it sits at the heart of virtually every significant application you use today. &lt;strong&gt;SQL&lt;/strong&gt;, which expands to &lt;strong&gt;Structured Query Language&lt;/strong&gt;, is a declarative programming language designed specifically for managing, organizing, and retrieving data stored in &lt;strong&gt;relational databases&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At its core, &lt;strong&gt;SQL&lt;/strong&gt; allows you to tell a database system what you want rather than how to retrieve it. This declarative nature distinguishes &lt;strong&gt;SQL&lt;/strong&gt; from imperative languages where you must write step-by-step instructions. The database engine handles the optimization, execution plan, and data access internally, freeing developers to focus on business logic instead of low-level file operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Database?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;database&lt;/strong&gt; is an organized collection of structured data that is stored and accessed electronically. Think of it as a highly efficient digital filing cabinet designed for speed, reliability, and concurrent access by thousands or even millions of users simultaneously.&lt;/p&gt;

&lt;p&gt;Unlike a simple spreadsheet or text file, a production &lt;strong&gt;database&lt;/strong&gt; must satisfy strict requirements: it must maintain &lt;strong&gt;data integrity&lt;/strong&gt;, support &lt;strong&gt;atomic transactions&lt;/strong&gt;, allow &lt;strong&gt;concurrent access&lt;/strong&gt; without corruption, provide &lt;strong&gt;backup and recovery&lt;/strong&gt; mechanisms, and scale as data volumes grow. These capabilities are delivered by specialized software known as a &lt;strong&gt;Relational Database Management System&lt;/strong&gt; (&lt;strong&gt;RDBMS&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;RDBMS&lt;/strong&gt; acts as the intermediary between your application and the raw data files on disk. It manages memory buffers, disk I/O, query optimization, concurrency control through locking and multiversion concurrency control (&lt;strong&gt;MVCC&lt;/strong&gt;), and crash recovery. Popular &lt;strong&gt;RDBMS&lt;/strong&gt; implementations include systems that follow the same fundamental principles you will master in this series.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Relational Model: The Theoretical Backbone
&lt;/h2&gt;

&lt;p&gt;The entire concept of &lt;strong&gt;SQL&lt;/strong&gt; rests on the &lt;strong&gt;relational model&lt;/strong&gt;, first formally defined by Edgar F. Codd. In this model, all data is represented in two-dimensional structures called &lt;strong&gt;tables&lt;/strong&gt; (also known as &lt;strong&gt;relations&lt;/strong&gt;). Each &lt;strong&gt;table&lt;/strong&gt; represents a specific entity or concept in your domain.&lt;/p&gt;

&lt;p&gt;The power of the &lt;strong&gt;relational model&lt;/strong&gt; comes from its mathematical foundation in set theory and predicate logic. This foundation guarantees that data can be combined, filtered, and transformed in predictable, mathematically sound ways. Relationships between &lt;strong&gt;tables&lt;/strong&gt; are expressed through shared values rather than physical pointers, providing flexibility and reducing data duplication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Principles of Relational Design
&lt;/h3&gt;

&lt;p&gt;Several core rules govern how data should be structured in a &lt;strong&gt;relational database&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomicity&lt;/strong&gt;: Each cell in a &lt;strong&gt;table&lt;/strong&gt; holds a single, indivisible value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uniqueness&lt;/strong&gt;: Every row in a &lt;strong&gt;table&lt;/strong&gt; must be uniquely identifiable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Order independence&lt;/strong&gt;: The sequence of rows or columns does not matter; the data is defined by its content and relationships.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt;: All values in a column must belong to the same &lt;strong&gt;data type&lt;/strong&gt; and follow the same rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These principles lead to the practice of &lt;strong&gt;normalization&lt;/strong&gt;, which organizes data to minimize redundancy while preserving relationships. Although we will explore normalization in greater depth later, understanding that it exists helps explain why &lt;strong&gt;SQL&lt;/strong&gt; databases feel so structured and reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tables: The Fundamental Building Blocks
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;table&lt;/strong&gt; is the primary structure where data lives. Each &lt;strong&gt;table&lt;/strong&gt; has a name that should clearly describe the entity it represents, such as &lt;code&gt;users&lt;/code&gt;, &lt;code&gt;orders&lt;/code&gt;, or &lt;code&gt;products&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside a &lt;strong&gt;table&lt;/strong&gt; you find:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Columns&lt;/strong&gt; (also called &lt;strong&gt;fields&lt;/strong&gt; or &lt;strong&gt;attributes&lt;/strong&gt;): These define the structure and type of data the &lt;strong&gt;table&lt;/strong&gt; can hold. Each &lt;strong&gt;column&lt;/strong&gt; has a name and a specific &lt;strong&gt;data type&lt;/strong&gt; that enforces what kind of information can be stored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rows&lt;/strong&gt; (also called &lt;strong&gt;records&lt;/strong&gt; or &lt;strong&gt;tuples&lt;/strong&gt;): These are the actual data entries. Each &lt;strong&gt;row&lt;/strong&gt; represents one complete instance of the entity described by the &lt;strong&gt;table&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, consider an e-commerce application. You might have a &lt;strong&gt;products&lt;/strong&gt; &lt;strong&gt;table&lt;/strong&gt; with columns like &lt;code&gt;product_id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;price&lt;/code&gt;, &lt;code&gt;category&lt;/code&gt;, and &lt;code&gt;stock_quantity&lt;/code&gt;. Each &lt;strong&gt;row&lt;/strong&gt; would represent one specific product available for sale.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visualizing Table Structure
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;table&lt;/strong&gt; can be imagined as a grid. The column headers define the blueprint, while each subsequent row fills in actual values according to that blueprint. The &lt;strong&gt;RDBMS&lt;/strong&gt; enforces rules at the column level, such as requiring certain columns to be filled (&lt;strong&gt;NOT NULL&lt;/strong&gt;) or ensuring values fall within acceptable ranges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rows, Columns, and Data Relationships
&lt;/h2&gt;

&lt;p&gt;Every &lt;strong&gt;row&lt;/strong&gt; in a &lt;strong&gt;table&lt;/strong&gt; must be uniquely identifiable. This is typically achieved using a &lt;strong&gt;primary key&lt;/strong&gt; — a column or combination of columns whose value is unique for every &lt;strong&gt;row&lt;/strong&gt;. The &lt;strong&gt;primary key&lt;/strong&gt; serves as the definitive address for that record.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Relationships&lt;/strong&gt; between &lt;strong&gt;tables&lt;/strong&gt; are established using &lt;strong&gt;foreign keys&lt;/strong&gt;. A &lt;strong&gt;foreign key&lt;/strong&gt; in one &lt;strong&gt;table&lt;/strong&gt; references the &lt;strong&gt;primary key&lt;/strong&gt; in another &lt;strong&gt;table&lt;/strong&gt;, creating a logical link. This linkage is what makes the database &lt;strong&gt;relational&lt;/strong&gt; — data in separate &lt;strong&gt;tables&lt;/strong&gt; can be meaningfully connected without duplicating entire records.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;An &lt;code&gt;orders&lt;/code&gt; &lt;strong&gt;table&lt;/strong&gt; might contain a &lt;code&gt;customer_id&lt;/code&gt; column that references the &lt;code&gt;customer_id&lt;/code&gt; &lt;strong&gt;primary key&lt;/strong&gt; in a &lt;code&gt;customers&lt;/code&gt; &lt;strong&gt;table&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;This design allows one customer to place many orders while storing customer details only once.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach dramatically reduces data redundancy, improves consistency, and makes complex queries possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why SQL and Relational Databases Dominate
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SQL&lt;/strong&gt; combined with the &lt;strong&gt;relational model&lt;/strong&gt; offers several powerful advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Declarative power&lt;/strong&gt;: You describe the desired result, and the &lt;strong&gt;query optimizer&lt;/strong&gt; determines the most efficient way to retrieve it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data integrity&lt;/strong&gt;: Built-in constraints protect against invalid data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardization&lt;/strong&gt;: &lt;strong&gt;SQL&lt;/strong&gt; is an ANSI/ISO standard, meaning core concepts transfer across different &lt;strong&gt;RDBMS&lt;/strong&gt; implementations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Well-designed &lt;strong&gt;relational databases&lt;/strong&gt; can handle terabytes of data while maintaining performance through proper indexing and query design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction safety&lt;/strong&gt;: Changes can be grouped into &lt;strong&gt;transactions&lt;/strong&gt; that either fully succeed or fully roll back.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, no technology is perfect. &lt;strong&gt;Relational databases&lt;/strong&gt; can face challenges with extremely high-velocity write workloads or when dealing with highly unstructured data. These limitations have led to the rise of other database types, but for structured business data — finance, e-commerce, healthcare, inventory, user management — the &lt;strong&gt;relational model&lt;/strong&gt; remains the gold standard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Developer Perspective
&lt;/h2&gt;

&lt;p&gt;As a software engineer, you will interact with &lt;strong&gt;SQL&lt;/strong&gt; daily. Whether building a new feature, debugging performance issues, or designing a new data model, a deep understanding of these foundational concepts prevents costly mistakes later.&lt;/p&gt;

&lt;p&gt;When designing &lt;strong&gt;tables&lt;/strong&gt;, always ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What entity does this &lt;strong&gt;table&lt;/strong&gt; represent?&lt;/li&gt;
&lt;li&gt;What are the natural relationships to other entities?&lt;/li&gt;
&lt;li&gt;Which columns must be unique?&lt;/li&gt;
&lt;li&gt;What constraints protect data quality?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions guide you toward clean, maintainable database schemas that scale gracefully as your application grows.&lt;/p&gt;

&lt;p&gt;If you are serious about mastering &lt;strong&gt;SQL&lt;/strong&gt; and want a complete hands-on playbook that follows this exact structured learning path with exercises, challenges, and advanced patterns, consider purchasing the SQL Playbook at &lt;a href="https://codewithdhanian.gumroad.com/l/hjmix" rel="noopener noreferrer"&gt;https://codewithdhanian.gumroad.com/l/hjmix&lt;/a&gt;. It is designed to complement this series perfectly.&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%2Fn2s7l102gz38kbc4bzkl.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%2Fn2s7l102gz38kbc4bzkl.png" alt="" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
    </item>
    <item>
      <title>Day 1: What is Linux – History, Distributions, and Philosophy</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Tue, 19 May 2026 04:32:02 +0000</pubDate>
      <link>https://dev.to/code_2/day-1-what-is-linux-history-distributions-and-philosophy-hef</link>
      <guid>https://dev.to/code_2/day-1-what-is-linux-history-distributions-and-philosophy-hef</guid>
      <description>&lt;p&gt;Linux is a powerful, open-source operating system kernel that powers everything from smartphones and personal computers to the world's largest supercomputers and cloud servers. At its core, &lt;strong&gt;Linux&lt;/strong&gt; refers specifically to the kernel originally developed by Linus Torvalds. When combined with the tools and utilities from the &lt;strong&gt;GNU Project&lt;/strong&gt;, it forms a complete operating system commonly known as &lt;strong&gt;GNU/Linux&lt;/strong&gt;.&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%2F45amakkb00qgg037inz4.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%2F45amakkb00qgg037inz4.png" alt="What is Linux? A visual guide" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Birth of Linux: A Hobby That Changed the World
&lt;/h3&gt;

&lt;p&gt;In 1991, Linus Torvalds, a Finnish computer science student at the University of Helsinki, grew frustrated with the limitations of existing systems like &lt;strong&gt;Minix&lt;/strong&gt;, a small Unix-like operating system used for educational purposes. Torvalds wanted a free, modifiable system that could run on his Intel 386 personal computer. &lt;/p&gt;

&lt;p&gt;On August 25, 1991, he posted a now-famous message to the comp.os.minix newsgroup:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I'm doing a (free) operating system (just a hobby, won't be big and professional like gnu) for 386(486) AT clones."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;He released the first version of the kernel, version 0.01, in September 1991. Initially, Torvalds distributed it under a license that restricted commercial use. In 1992, he switched to the &lt;strong&gt;GNU General Public License (GPL)&lt;/strong&gt; version 2. This decision was pivotal: it allowed anyone to view, modify, and distribute the source code, provided that derivative works remained under the same license. This &lt;strong&gt;copyleft&lt;/strong&gt; mechanism ensured that Linux remained free and open forever.&lt;/p&gt;

&lt;p&gt;By combining the &lt;strong&gt;Linux kernel&lt;/strong&gt; with the nearly complete &lt;strong&gt;GNU operating system&lt;/strong&gt; tools (such as the GNU Compiler Collection, Bash shell, and core utilities), developers created a fully functional, free Unix-like operating system. Richard Stallman of the Free Software Foundation has long advocated referring to it as &lt;strong&gt;GNU/Linux&lt;/strong&gt; to acknowledge the essential contributions of the GNU Project.&lt;/p&gt;

&lt;h3&gt;
  
  
  The GNU Project and the Philosophy of Free Software
&lt;/h3&gt;

&lt;p&gt;The foundation of Linux's philosophy traces back to 1983, when &lt;strong&gt;Richard Stallman&lt;/strong&gt; launched the &lt;strong&gt;GNU Project&lt;/strong&gt; ("GNU's Not Unix"). Stallman, a programmer at MIT, witnessed the shift from collaborative software sharing in the 1970s to proprietary, closed-source software in the 1980s. Companies began restricting access to source code, preventing users from studying, modifying, or sharing programs.&lt;/p&gt;

&lt;p&gt;Stallman defined &lt;strong&gt;free software&lt;/strong&gt; through four essential freedoms (often called the "Four Freedoms"):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Freedom 0&lt;/strong&gt;: The freedom to run the program as you wish, for any purpose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freedom 1&lt;/strong&gt;: The freedom to study how the program works and change it to suit your needs (access to the source code is a precondition).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freedom 2&lt;/strong&gt;: The freedom to redistribute copies so you can help your neighbor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freedom 3&lt;/strong&gt;: The freedom to improve the program and release your improvements to the public so that the whole community benefits (again, source code access is required).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These freedoms emphasize user liberty, not price. "Free" refers to freedom, like free speech, not free beer. The &lt;strong&gt;GNU General Public License (GPL)&lt;/strong&gt; enforces these freedoms through copyleft, ensuring that modified versions remain free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linus Torvalds&lt;/strong&gt; took a more pragmatic approach. He focused on technical excellence and collaboration, viewing open development as the best way to create high-quality software. This blend of Stallman's idealism and Torvalds' pragmatism fueled Linux's explosive growth. Today, thousands of developers worldwide contribute to the kernel through platforms like Git.&lt;/p&gt;

&lt;p&gt;Linux embodies core principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Openness&lt;/strong&gt;: Source code is publicly available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration&lt;/strong&gt;: Global community-driven development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stability and Security&lt;/strong&gt;: Rigorous peer review reduces bugs and vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability&lt;/strong&gt;: Runs on diverse hardware architectures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency&lt;/strong&gt;: Lightweight and highly customizable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Linux Distributions: Flavors for Every Need
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Linux distribution&lt;/strong&gt; (or &lt;strong&gt;distro&lt;/strong&gt;) is a complete operating system built around the Linux kernel, bundled with the GNU tools, a package manager, desktop environment (or lack thereof for servers), and additional software. Distributions make Linux accessible by handling installation, updates, and hardware support.&lt;/p&gt;

&lt;p&gt;Major families of distributions include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debian-based distributions&lt;/strong&gt; use the &lt;code&gt;.deb&lt;/code&gt; package format and the &lt;strong&gt;APT&lt;/strong&gt; package manager. They emphasize stability.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Debian&lt;/strong&gt;: The parent distribution, known for rock-solid reliability and vast software repositories. It follows a strict free software philosophy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ubuntu&lt;/strong&gt;: Created by Canonical in 2004, Ubuntu is user-friendly with regular releases (every six months, with Long Term Support versions every two years). It powers many desktops, servers, and cloud instances. Its philosophy prioritizes accessibility and community support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux Mint&lt;/strong&gt;: Built on Ubuntu, Mint focuses on a polished, Windows-like experience with the Cinnamon desktop. It is ideal for beginners transitioning from other operating systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Red Hat-based distributions&lt;/strong&gt; use the &lt;code&gt;.rpm&lt;/code&gt; package format and tools like &lt;strong&gt;YUM&lt;/strong&gt; or &lt;strong&gt;DNF&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fedora&lt;/strong&gt;: Sponsored by Red Hat, Fedora serves as a testing ground for cutting-edge technologies that later appear in enterprise products. It targets developers and enthusiasts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Red Hat Enterprise Linux (RHEL)&lt;/strong&gt;: A commercial distribution with paid support, widely used in business environments for its stability and long support cycles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CentOS Stream&lt;/strong&gt; (and community forks like AlmaLinux and Rocky Linux): Free alternatives providing binary compatibility with RHEL for production servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other notable distributions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arch Linux&lt;/strong&gt;: A rolling-release distro where users build the system from minimal components. It follows the "keep it simple" philosophy and appeals to advanced users who value customization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gentoo&lt;/strong&gt;: Highly optimized; users compile software from source for maximum performance on their specific hardware.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each distribution balances trade-offs between stability, latest features, ease of use, and target audience. Choosing one depends on your goals—beginner desktop, secure server, or development workstation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the Linux Ecosystem in Practice
&lt;/h3&gt;

&lt;p&gt;When you install a Linux distribution, you receive more than just the kernel. You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;kernel&lt;/strong&gt; managing hardware, processes, and memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GNU tools&lt;/strong&gt; for core functionality.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;shell&lt;/strong&gt; (usually Bash) for command-line interaction.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;package manager&lt;/strong&gt; for installing and updating software.&lt;/li&gt;
&lt;li&gt;Optional graphical interfaces like GNOME, KDE Plasma, or XFCE.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example of basic system identification commands&lt;/strong&gt; (these will work on almost any Linux system):&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="c"&gt;# View kernel version and system information&lt;/span&gt;
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;

&lt;span class="c"&gt;# Display detailed distribution information&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/os-release

&lt;span class="c"&gt;# Check CPU and hardware details&lt;/span&gt;
lscpu
lsblk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands reveal the layered nature of Linux: the kernel at the base, user-space tools above it, and your chosen distribution providing the complete experience.&lt;/p&gt;

&lt;p&gt;Linux's strength lies in its adaptability. You can strip it down to a minimal server or expand it into a full multimedia workstation. Its philosophy of freedom empowers users to own their computing experience rather than being locked into proprietary ecosystems.&lt;/p&gt;

&lt;p&gt;This foundational understanding of Linux's origins, guiding principles, and variety of distributions sets the stage for mastering the system. The collaborative spirit that birthed Linux continues today through millions of users and developers worldwide.&lt;/p&gt;

&lt;p&gt;If you are serious about achieving true Linux mastery—from beginner commands to advanced administration, security, scripting, and production server deployment—consider investing in a comprehensive resource. The &lt;strong&gt;Linux Mastery Ebook&lt;/strong&gt; available at &lt;a href="https://codewithdhanian.gumroad.com/l/hqtbxt" rel="noopener noreferrer"&gt;https://codewithdhanian.gumroad.com/l/hqtbxt&lt;/a&gt; provides structured, hands-on guidance that builds directly on these fundamentals and takes you far beyond them.&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%2Fw6wxmef0pbplnq1qjwqv.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%2Fw6wxmef0pbplnq1qjwqv.png" alt="Linux history" width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
    </item>
    <item>
      <title>CONCEPT 1: Linux Installation Methods (Dual Boot, VM, Bare Metal)</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Mon, 18 May 2026 13:20:14 +0000</pubDate>
      <link>https://dev.to/code_2/concept-1-linux-installation-methods-dual-boot-vm-bare-metal-eg0</link>
      <guid>https://dev.to/code_2/concept-1-linux-installation-methods-dual-boot-vm-bare-metal-eg0</guid>
      <description>&lt;p&gt;Choosing how to install &lt;strong&gt;Linux&lt;/strong&gt; is one of the most foundational decisions a system administrator, developer, or enthusiast will make. The installation method directly influences performance, isolation, hardware access, ease of experimentation, and long-term maintainability. The three primary approaches—&lt;strong&gt;bare metal&lt;/strong&gt;, &lt;strong&gt;virtual machine (VM)&lt;/strong&gt;, and &lt;strong&gt;dual boot&lt;/strong&gt;—each solve different problems and come with distinct trade-offs in architecture, workflow, and operational behavior.&lt;/p&gt;

&lt;p&gt;This chapter explores each method in depth, from the underlying system architecture to practical implementation, real-world engineering considerations, and advanced usage patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Installation Landscape
&lt;/h2&gt;

&lt;p&gt;At its core, installing &lt;strong&gt;Linux&lt;/strong&gt; means placing a functional &lt;strong&gt;kernel&lt;/strong&gt;, &lt;strong&gt;init system&lt;/strong&gt; (most commonly &lt;strong&gt;systemd&lt;/strong&gt;), &lt;strong&gt;root filesystem&lt;/strong&gt;, and necessary &lt;strong&gt;userspace&lt;/strong&gt; tools onto a storage medium that the &lt;strong&gt;bootloader&lt;/strong&gt; can locate and execute.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Linux kernel&lt;/strong&gt; is a monolithic kernel that interacts directly with hardware through &lt;strong&gt;drivers&lt;/strong&gt; compiled either statically or as loadable &lt;strong&gt;kernel modules&lt;/strong&gt;. The &lt;strong&gt;bootloader&lt;/strong&gt; (typically &lt;strong&gt;GRUB&lt;/strong&gt;) is responsible for loading the kernel image (&lt;code&gt;vmlinuz&lt;/code&gt;), initial ramdisk (&lt;code&gt;initrd&lt;/code&gt; or &lt;code&gt;initramfs&lt;/code&gt;), and passing kernel parameters.&lt;/p&gt;

&lt;p&gt;Each installation method changes where and how this stack executes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bare metal&lt;/strong&gt; runs the kernel directly on physical CPU, memory, and devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Virtual machine&lt;/strong&gt; runs the kernel inside a hypervisor-managed environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dual boot&lt;/strong&gt; shares physical hardware between two operating systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bare Metal Installation: Maximum Performance and Direct Hardware Control
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bare metal&lt;/strong&gt; installation means &lt;strong&gt;Linux&lt;/strong&gt; runs natively on the physical hardware without any abstraction layer between the kernel and the CPU, memory, storage controllers, or peripherals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Choose Bare Metal?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bare metal&lt;/strong&gt; delivers the highest possible performance because there is zero hypervisor overhead. All CPU cycles, memory bandwidth, and I/O operations go directly to your &lt;strong&gt;Linux&lt;/strong&gt; environment. This approach is preferred for production servers, high-performance computing, gaming desktops, audio/video workstations, and any workload where latency or throughput is critical.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hardware Preparation and UEFI vs BIOS
&lt;/h3&gt;

&lt;p&gt;Modern systems use &lt;strong&gt;UEFI&lt;/strong&gt; (Unified Extensible Firmware Interface) with &lt;strong&gt;GPT&lt;/strong&gt; partitioning. Legacy systems may still use &lt;strong&gt;BIOS&lt;/strong&gt; with &lt;strong&gt;MBR&lt;/strong&gt;. During installation, you must decide on an &lt;strong&gt;EFI System Partition (ESP)&lt;/strong&gt; formatted as FAT32 (typically 512 MiB) mounted at &lt;code&gt;/boot/efi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A recommended bare metal partition layout for a production system might 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;/dev/nvme0n1p1     512M     FAT32     /boot/efi     (ESP)
/dev/nvme0n1p2     1G       ext4      /boot
/dev/nvme0n1p3     remaining space    LVM physical volume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;LVM&lt;/strong&gt; (Logical Volume Manager) is strongly recommended because it allows online resizing of logical volumes without downtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step Bare Metal Installation Process
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create bootable media using &lt;code&gt;dd&lt;/code&gt;, Rufus, or Ventoy.&lt;/li&gt;
&lt;li&gt;Boot from the media and enter the live environment.&lt;/li&gt;
&lt;li&gt;Partition disks using &lt;code&gt;gdisk&lt;/code&gt;, &lt;code&gt;fdisk&lt;/code&gt;, or the distribution installer.&lt;/li&gt;
&lt;li&gt;Format partitions (&lt;code&gt;mkfs.ext4&lt;/code&gt;, &lt;code&gt;mkfs.fat&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;Mount the target filesystem hierarchy under &lt;code&gt;/mnt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;debootstrap&lt;/code&gt;, &lt;code&gt;pacstrap&lt;/code&gt;, or the graphical installer to populate the root filesystem.&lt;/li&gt;
&lt;li&gt;Generate &lt;code&gt;fstab&lt;/code&gt;, chroot into the new system, install the bootloader, and configure networking.&lt;/li&gt;
&lt;li&gt;Reboot and remove installation media.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Advanced Considerations
&lt;/h3&gt;

&lt;p&gt;On bare metal, you have full control over &lt;strong&gt;kernel parameters&lt;/strong&gt; passed via GRUB (&lt;code&gt;quiet splash&lt;/code&gt;, &lt;code&gt;mitigations=off&lt;/code&gt;, &lt;code&gt;iommu=pt&lt;/code&gt;). You can compile a custom kernel tailored to your hardware, enable specific &lt;strong&gt;CPU features&lt;/strong&gt; (AVX512, huge pages), and optimize &lt;strong&gt;I/O schedulers&lt;/strong&gt; (&lt;code&gt;mq-deadline&lt;/code&gt;, &lt;code&gt;bfq&lt;/code&gt;, or &lt;code&gt;none&lt;/code&gt; for NVMe).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitations&lt;/strong&gt;: No easy rollback. Hardware failures affect the entire system. Testing new distributions requires physical hardware or reinstallation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual Machine Installation: Isolation, Flexibility, and Rapid Experimentation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Virtual machines&lt;/strong&gt; run &lt;strong&gt;Linux&lt;/strong&gt; inside a hypervisor such as &lt;strong&gt;KVM/QEMU&lt;/strong&gt;, &lt;strong&gt;VirtualBox&lt;/strong&gt;, &lt;strong&gt;VMware&lt;/strong&gt;, or &lt;strong&gt;Hyper-V&lt;/strong&gt;. The hypervisor presents virtualized hardware (vCPU, vRAM, virtio devices) to the guest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture of Modern Virtualization
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;KVM&lt;/strong&gt; (Kernel-based Virtual Machine) turns the &lt;strong&gt;Linux&lt;/strong&gt; kernel into a hypervisor by loading the &lt;code&gt;kvm&lt;/code&gt; and &lt;code&gt;kvm-intel&lt;/code&gt;/&lt;code&gt;kvm-amd&lt;/code&gt; modules. &lt;strong&gt;QEMU&lt;/strong&gt; provides device emulation, while &lt;strong&gt;virtio&lt;/strong&gt; drivers deliver near-native performance for block, network, and graphics devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;libvirt&lt;/strong&gt; acts as a management layer, providing a unified API for creating, starting, and monitoring virtual machines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a High-Performance Linux VM
&lt;/h3&gt;

&lt;p&gt;Here is a complete example using &lt;code&gt;virt-install&lt;/code&gt; (recommended for production-grade VMs):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;virt-install &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; ubuntu-server-24 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ram&lt;/span&gt; 8192 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vcpus&lt;/span&gt; 8 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cpu&lt;/span&gt; host-passthrough &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--disk&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/lib/libvirt/images/ubuntu24.qcow2,size&lt;span class="o"&gt;=&lt;/span&gt;80,format&lt;span class="o"&gt;=&lt;/span&gt;qcow2,bus&lt;span class="o"&gt;=&lt;/span&gt;virtio &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network&lt;/span&gt; &lt;span class="nv"&gt;network&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;default,model&lt;span class="o"&gt;=&lt;/span&gt;virtio &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--graphics&lt;/span&gt; none &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--console&lt;/span&gt; pty,target_type&lt;span class="o"&gt;=&lt;/span&gt;serial &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--location&lt;/span&gt; https://releases.ubuntu.com/24.04/ubuntu-24.04-live-server-amd64.iso &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--extra-args&lt;/span&gt; &lt;span class="s1"&gt;'console=ttyS0,115200n8'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key options explained&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--cpu host-passthrough&lt;/code&gt;: Exposes the full host CPU capabilities to the guest for maximum performance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;virtio&lt;/code&gt; drivers: Paravirtualized devices that bypass much of the emulation overhead.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;qcow2&lt;/code&gt; format: Supports snapshots, compression, and thin provisioning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Advanced VM Techniques
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PCI passthrough&lt;/strong&gt;: Assign physical GPUs, NICs, or storage controllers directly to the VM using &lt;strong&gt;VFIO&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nested virtualization&lt;/strong&gt;: Run VMs inside VMs (useful for testing &lt;strong&gt;Kubernetes&lt;/strong&gt; clusters).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live migration&lt;/strong&gt;: Move running VMs between hosts with zero downtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;: Snapshots, easy cloning, hardware independence, and the ability to run multiple distributions simultaneously.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Limitations&lt;/strong&gt;: Slight performance overhead (typically 2-10% for CPU-bound tasks, higher for I/O without virtio). Resource contention on the host.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dual Boot: Sharing Physical Hardware Between Operating Systems
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Dual boot&lt;/strong&gt; allows both &lt;strong&gt;Linux&lt;/strong&gt; and another OS (usually &lt;strong&gt;Windows&lt;/strong&gt;) to coexist on the same physical machine, with the &lt;strong&gt;bootloader&lt;/strong&gt; presenting a choice at startup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bootloader Architecture in Dual Boot
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GRUB&lt;/strong&gt; is installed to the &lt;strong&gt;EFI System Partition&lt;/strong&gt; and configured to detect other operating systems via &lt;code&gt;os-prober&lt;/code&gt;. The chainloading mechanism works as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;UEFI firmware loads &lt;code&gt;GRUB.efi&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;GRUB reads its configuration (&lt;code&gt;/boot/grub/grub.cfg&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Menu is displayed with entries for Linux and Windows.&lt;/li&gt;
&lt;li&gt;Selecting Windows chainloads the &lt;strong&gt;Windows Boot Manager&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Safe Dual Boot Installation Strategy
&lt;/h3&gt;

&lt;p&gt;Always install &lt;strong&gt;Windows&lt;/strong&gt; first. Windows will claim the entire disk and create its own partitions (EFI, MSR, Windows, Recovery). Then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Shrink the Windows partition from within Windows using Disk Management or &lt;code&gt;diskpart&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Boot from Linux media.&lt;/li&gt;
&lt;li&gt;Install Linux into the unallocated space.&lt;/li&gt;
&lt;li&gt;Let the Linux installer install &lt;strong&gt;GRUB&lt;/strong&gt; to the EFI partition (it will automatically detect Windows).&lt;/li&gt;
&lt;li&gt;Update GRUB configuration: &lt;code&gt;sudo update-grub&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Common Challenges and Solutions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fast Startup&lt;/strong&gt; in Windows can leave NTFS partitions in an inconsistent state. Disable it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time synchronization&lt;/strong&gt;: Windows uses local time, Linux uses UTC. Set Linux to use local time or Windows to use UTC.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Boot&lt;/strong&gt;: Sign your custom kernels or use distribution-provided signed bootloaders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared data partition&lt;/strong&gt;: Create an NTFS or exFAT partition accessible by both systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;: Native performance for both OSes, access to hardware-specific applications.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Limitations&lt;/strong&gt;: Risk of bootloader corruption, difficulty in resizing partitions later, and inability to run both OSes simultaneously.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the Right Method: Decision Framework
&lt;/h2&gt;

&lt;p&gt;Consider these factors when deciding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance needs&lt;/strong&gt;: Bare metal for maximum speed, VM for acceptable performance with isolation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Experimentation frequency&lt;/strong&gt;: VM wins for rapid testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardware availability&lt;/strong&gt;: Dual boot or bare metal when you have dedicated machines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production requirements&lt;/strong&gt;: Bare metal or Type-1 hypervisor (KVM) for servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development workflow&lt;/strong&gt;: Many engineers maintain a bare metal workstation for daily work and multiple VMs for isolated testing environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best practice&lt;/strong&gt;: Start with a &lt;strong&gt;virtual machine&lt;/strong&gt; to learn safely, move to &lt;strong&gt;dual boot&lt;/strong&gt; for daily driver usage, and deploy to &lt;strong&gt;bare metal&lt;/strong&gt; for production workloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Engineering Workflows
&lt;/h2&gt;

&lt;p&gt;Professional Linux users often combine methods. A common setup includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bare metal host running &lt;strong&gt;KVM&lt;/strong&gt; + &lt;strong&gt;libvirt&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Multiple specialized VMs (development, testing, CI/CD).&lt;/li&gt;
&lt;li&gt;Physical dual-boot machine for graphics-intensive work.&lt;/li&gt;
&lt;li&gt;Cloud instances for additional capacity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This hybrid approach provides both performance and flexibility.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>beginners</category>
      <category>linux</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What is Horizontal vs Vertical Scaling?</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Fri, 08 May 2026 08:03:13 +0000</pubDate>
      <link>https://dev.to/code_2/what-is-horizontal-vs-vertical-scaling-1o3e</link>
      <guid>https://dev.to/code_2/what-is-horizontal-vs-vertical-scaling-1o3e</guid>
      <description>&lt;p&gt;&lt;strong&gt;Scaling&lt;/strong&gt; is the fundamental process of increasing a system’s capacity to handle greater workloads, more users, or higher traffic without compromising performance. In system design, two primary strategies exist: &lt;strong&gt;vertical scaling&lt;/strong&gt; and &lt;strong&gt;horizontal scaling&lt;/strong&gt;. Each approach addresses growth differently, carries unique architectural implications, and demands distinct engineering considerations. Understanding both is essential for building systems that remain reliable, cost-effective, and performant as demand evolves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Vertical Scaling
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Vertical scaling&lt;/strong&gt;, also known as &lt;strong&gt;scaling up&lt;/strong&gt;, involves enhancing the capabilities of a single server or instance by adding more resources to it. This typically means increasing CPU cores, RAM, storage capacity, or network bandwidth on the existing machine.&lt;/p&gt;

&lt;p&gt;The process is straightforward. Consider a web server running on a machine with 4 CPU cores and 8 GB of RAM. When traffic grows, the operations team upgrades that same machine to 16 CPU cores and 64 GB of RAM. No additional servers are introduced; the workload continues to run on the upgraded hardware.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vertical scaling&lt;/strong&gt; shines in scenarios where the application is monolithic or tightly coupled to a single process. Databases often benefit from this approach during early growth phases because a larger instance can process more queries per second without requiring data partitioning logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages of vertical scaling&lt;/strong&gt; include simplicity of implementation, lower operational overhead, and minimal changes to application code. Latency between components remains low since everything runs within one machine. Management is easier because there is only a single instance to monitor, backup, and secure.&lt;/p&gt;

&lt;p&gt;However, &lt;strong&gt;vertical scaling&lt;/strong&gt; has hard physical limits. Hardware vendors offer only finite maximum configurations for any server type. Beyond a certain point, upgrading becomes prohibitively expensive or technically impossible. A single point of failure exists: if that upgraded machine crashes, the entire system goes down. Upgrades frequently require downtime while the instance is stopped, resized, and restarted. In cloud environments, this translates to higher costs for larger instance types that may be over-provisioned during low-traffic periods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Horizontal Scaling
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Horizontal scaling&lt;/strong&gt;, also known as &lt;strong&gt;scaling out&lt;/strong&gt;, involves adding more servers or instances to distribute the workload across multiple machines. Instead of making one server more powerful, the system grows by increasing the number of identical servers working together.&lt;/p&gt;

&lt;p&gt;A load balancer sits in front of the fleet of servers and routes incoming requests intelligently across them. As demand increases, new instances are spun up automatically or manually, and traffic is spread evenly. This approach aligns naturally with cloud-native architectures and microservices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Horizontal scaling&lt;/strong&gt; provides virtually unlimited growth potential because additional machines can be added indefinitely. It delivers built-in fault tolerance: if one server fails, the remaining servers continue serving traffic. Cost efficiency improves because smaller, commodity instances are cheaper than a single massive machine. Upgrades can occur without downtime by adding new instances before removing old ones.&lt;/p&gt;

&lt;p&gt;The trade-offs are significant. &lt;strong&gt;Horizontal scaling&lt;/strong&gt; introduces complexity in areas such as data synchronization, session management, and inter-service communication. Network latency between machines becomes a factor. Applications must be designed to be stateless or use external shared stores for state. Distributed system challenges like consistency, leader election, and failure detection emerge. Debugging across multiple nodes is more difficult than on a single machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparing Vertical and Horizontal Scaling in Practice
&lt;/h3&gt;

&lt;p&gt;The choice between &lt;strong&gt;vertical scaling&lt;/strong&gt; and &lt;strong&gt;horizontal scaling&lt;/strong&gt; depends on the application’s architecture, expected growth curve, team expertise, and budget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vertical scaling&lt;/strong&gt; suits early-stage startups, legacy monolithic applications, or workloads with heavy in-memory computations where splitting data is impractical. &lt;strong&gt;Horizontal scaling&lt;/strong&gt; becomes necessary when traffic exceeds what any single machine can handle or when high availability is non-negotiable.&lt;/p&gt;

&lt;p&gt;Real-world systems frequently combine both strategies. A database might use &lt;strong&gt;vertical scaling&lt;/strong&gt; for its primary instance while employing &lt;strong&gt;horizontal scaling&lt;/strong&gt; through read replicas or sharded clusters for read-heavy workloads.&lt;/p&gt;

&lt;h3&gt;
  
  
  Designing Applications for Horizontal Scaling: A Practical Example
&lt;/h3&gt;

&lt;p&gt;To succeed with &lt;strong&gt;horizontal scaling&lt;/strong&gt;, applications must be stateless whenever possible. The following complete code example illustrates the difference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stateful example (problematic for horizontal scaling)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# Global variable stored in memory
&lt;/span&gt;
&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/increment&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Counter: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this service runs on multiple instances behind a load balancer, each instance maintains its own counter. Users hitting different instances receive inconsistent values. This breaks correctness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stateless example (ready for horizontal scaling)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;redis_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;redis-shared-store&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/increment&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;incr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;global_counter&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Counter: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All instances share the same Redis store. The counter remains consistent regardless of which instance processes the request. This design scales horizontally without modification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Horizontal Scaling with Nginx Load Balancer
&lt;/h3&gt;

&lt;p&gt;A complete Nginx configuration demonstrates how to distribute traffic across multiple application instances.&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="c1"&gt;# /etc/nginx/nginx.conf&lt;/span&gt;
&lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="s"&gt;www-data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;worker_processes&lt;/span&gt; &lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pid&lt;/span&gt; &lt;span class="n"&gt;/run/nginx.pid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;worker_connections&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;app-instance-1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;app-instance-2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;app-instance-3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;# Add more servers here as you scale out&lt;/span&gt;
        &lt;span class="kn"&gt;least_conn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;# Distribute to the least busy server&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&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="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;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;# Health checks for automatic removal of unhealthy instances&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_next_upstream&lt;/span&gt; &lt;span class="s"&gt;error&lt;/span&gt; &lt;span class="s"&gt;timeout&lt;/span&gt; &lt;span class="s"&gt;http_500&lt;/span&gt; &lt;span class="s"&gt;http_502&lt;/span&gt; &lt;span class="s"&gt;http_503&lt;/span&gt; &lt;span class="s"&gt;http_504&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration defines an &lt;strong&gt;upstream&lt;/strong&gt; block listing all application instances. The &lt;strong&gt;least_conn&lt;/strong&gt; directive ensures intelligent load distribution. Proxy headers preserve original client information. As demand grows, simply add more &lt;strong&gt;server&lt;/strong&gt; lines or use orchestration tools to dynamically update the upstream list. Reload Nginx with &lt;code&gt;nginx -s reload&lt;/code&gt; to apply changes without downtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Choose Each Strategy
&lt;/h3&gt;

&lt;p&gt;Start with &lt;strong&gt;vertical scaling&lt;/strong&gt; when the system is small, the team is focused on rapid feature delivery, and the application does not yet require distributed coordination. Transition to &lt;strong&gt;horizontal scaling&lt;/strong&gt; when traffic patterns show sustained growth, when downtime during upgrades becomes unacceptable, or when cloud costs for larger instances exceed the expense of multiple smaller ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Horizontal scaling&lt;/strong&gt; is the foundation of modern resilient systems. It forces thoughtful design decisions that pay dividends in reliability and flexibility far beyond raw capacity.&lt;/p&gt;

&lt;p&gt;If you found this deep dive into &lt;strong&gt;horizontal versus vertical scaling&lt;/strong&gt; valuable and want the complete professional treatment of all 100 system design concepts with diagrams, real-world architectures, and production-ready patterns, grab the full system design ebook at &lt;a href="https://codewithdhanian.gumroad.com/l/urcjee" rel="noopener noreferrer"&gt;https://codewithdhanian.gumroad.com/l/urcjee&lt;/a&gt;. If this content helped you, consider buying me a coffee at &lt;a href="https://ko-fi.com/codewithdhanian" rel="noopener noreferrer"&gt;https://ko-fi.com/codewithdhanian&lt;/a&gt; to support more free in-depth resources like this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visualizing the Concept&lt;/strong&gt;&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%2Fgn4kwj66bavf8lpz6d5m.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%2Fgn4kwj66bavf8lpz6d5m.png" alt="Horizontal vs vertical scaling comparison" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
    </item>
    <item>
      <title>What is Load Balancing?</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Fri, 08 May 2026 07:43:53 +0000</pubDate>
      <link>https://dev.to/code_2/what-is-load-balancing-5egi</link>
      <guid>https://dev.to/code_2/what-is-load-balancing-5egi</guid>
      <description>&lt;p&gt;&lt;strong&gt;Load balancing&lt;/strong&gt; is the fundamental technique used in modern distributed systems to distribute incoming network traffic across multiple backend &lt;strong&gt;servers&lt;/strong&gt; or &lt;strong&gt;resources&lt;/strong&gt; in order to ensure no single server becomes overwhelmed, thereby improving &lt;strong&gt;responsiveness&lt;/strong&gt;, &lt;strong&gt;availability&lt;/strong&gt;, and &lt;strong&gt;scalability&lt;/strong&gt;. At its core, a &lt;strong&gt;load balancer&lt;/strong&gt; acts as a traffic cop that sits between clients and the actual application servers, intelligently routing each request to the most appropriate server based on predefined rules and real-time conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Load Balancing Is Essential in System Design
&lt;/h3&gt;

&lt;p&gt;In any production-grade application that serves millions of users, relying on a single server is impractical and risky. A sudden spike in traffic, such as during a flash sale or viral event, can cause that server to slow down, crash, or become unresponsive. &lt;strong&gt;Load balancing&lt;/strong&gt; solves this by enabling &lt;strong&gt;horizontal scaling&lt;/strong&gt; — the ability to add more servers dynamically — while maintaining a seamless user experience. It also provides &lt;strong&gt;fault tolerance&lt;/strong&gt;: if one server fails, the &lt;strong&gt;load balancer&lt;/strong&gt; automatically stops sending traffic to it and redirects requests to healthy servers. This ensures the system remains highly available even during hardware failures, maintenance windows, or unexpected load surges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Components of a Load Balancer
&lt;/h3&gt;

&lt;p&gt;A typical &lt;strong&gt;load balancer&lt;/strong&gt; consists of the following essential elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend Listener&lt;/strong&gt;: The entry point that accepts incoming client requests on specific ports (usually 80 for HTTP or 443 for HTTPS).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend Pool&lt;/strong&gt;: A group of healthy application servers (often called targets or origins) that actually process the requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health Check Mechanism&lt;/strong&gt;: Continuous monitoring that probes each backend server to verify it is responding correctly. A failed health check removes the server from the active pool until it recovers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routing Engine&lt;/strong&gt;: The brain that applies &lt;strong&gt;load balancing algorithms&lt;/strong&gt; and rules to decide which server receives each request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session Persistence Layer&lt;/strong&gt; (optional): Ensures that a user’s subsequent requests are routed to the same server when necessary (also known as sticky sessions).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Load Balancing Works Step by Step
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;A client (browser, mobile app, or another service) sends a request to the public IP or domain of the &lt;strong&gt;load balancer&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;load balancer&lt;/strong&gt; inspects the request headers, source IP, or other metadata.&lt;/li&gt;
&lt;li&gt;Using its configured algorithm and current server metrics (CPU load, active connections, response time), the &lt;strong&gt;load balancer&lt;/strong&gt; selects the optimal backend server.&lt;/li&gt;
&lt;li&gt;The request is forwarded (proxied) to the chosen server.&lt;/li&gt;
&lt;li&gt;The backend server processes the request and sends the response back through the &lt;strong&gt;load balancer&lt;/strong&gt; to the client.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;load balancer&lt;/strong&gt; may also perform TLS termination, compression, or request rewriting before forwarding.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Types of Load Balancers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Load balancers&lt;/strong&gt; are broadly classified into two layers of the OSI model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Layer 4 (Transport Layer) Load Balancers&lt;/strong&gt;: Operate at the TCP/UDP level. They forward packets based on IP address and port without inspecting the actual content of the request. Examples include AWS Network Load Balancer and HAProxy in TCP mode. They are extremely fast and suitable for high-throughput scenarios but cannot make routing decisions based on HTTP headers or URL paths.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Layer 7 (Application Layer) Load Balancers&lt;/strong&gt;: Operate at the HTTP/HTTPS level. They can read the full request, including URL, headers, cookies, and method. This allows advanced routing such as sending image requests to one pool and API requests to another. Examples include AWS Application Load Balancer, NGINX, and Envoy. They support content-based routing, rate limiting, and header manipulation but introduce slightly higher latency due to inspection.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Load balancers&lt;/strong&gt; can also be deployed as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hardware appliances&lt;/strong&gt; (F5 BIG-IP, Citrix ADC) — expensive but offer high performance and specialized ASIC chips.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Software solutions&lt;/strong&gt; (NGINX, HAProxy, Traefik) — run on commodity servers or containers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud-managed services&lt;/strong&gt; (AWS ELB, Google Cloud Load Balancing, Azure Load Balancer) — fully managed with auto-scaling built in.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Popular Load Balancing Algorithms
&lt;/h3&gt;

&lt;p&gt;The choice of algorithm directly impacts system performance. Here are the most widely used ones with detailed explanations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Round Robin&lt;/strong&gt;: Requests are distributed sequentially across the backend servers in a cyclic order. Simple and fair when all servers have identical capacity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Weighted Round Robin&lt;/strong&gt;: Each server is assigned a weight based on its capacity. A more powerful server receives proportionally more requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Least Connections&lt;/strong&gt;: The &lt;strong&gt;load balancer&lt;/strong&gt; routes the next request to the server currently handling the fewest active connections. Excellent for uneven workloads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Least Response Time&lt;/strong&gt;: Routes to the server with the lowest average response time, combining connection count and latency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;IP Hash&lt;/strong&gt;: Uses the client’s IP address to consistently route requests to the same server. Useful for session persistence without cookies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Random&lt;/strong&gt;: Selects a server at random. Surprisingly effective and simple to implement.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Complete NGINX Configuration Example
&lt;/h3&gt;

&lt;p&gt;Below is a production-ready NGINX configuration that demonstrates &lt;strong&gt;load balancing&lt;/strong&gt; with health checks, weighted round robin, and session persistence. Every line is explained in detail.&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="c1"&gt;# Global settings&lt;/span&gt;
&lt;span class="k"&gt;worker_processes&lt;/span&gt; &lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;worker_connections&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Define the upstream (backend pool)&lt;/span&gt;
    &lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend_servers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# Least Connections algorithm with weights&lt;/span&gt;
        &lt;span class="kn"&gt;least_conn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;app-server-1.example.com&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt; &lt;span class="s"&gt;weight=3&lt;/span&gt; &lt;span class="s"&gt;max_fails=3&lt;/span&gt; &lt;span class="s"&gt;fail_timeout=30s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;app-server-2.example.com&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt; &lt;span class="s"&gt;weight=2&lt;/span&gt; &lt;span class="s"&gt;max_fails=3&lt;/span&gt; &lt;span class="s"&gt;fail_timeout=30s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;app-server-3.example.com&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt; &lt;span class="s"&gt;weight=1&lt;/span&gt; &lt;span class="s"&gt;max_fails=3&lt;/span&gt; &lt;span class="s"&gt;fail_timeout=30s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;# Health check (requires nginx-plus or open-source module)&lt;/span&gt;
        &lt;span class="c1"&gt;# In open-source NGINX, use external tools like consul-template&lt;/span&gt;
        &lt;span class="kn"&gt;keepalive&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&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;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&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;myapp.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;# SSL termination happens here&lt;/span&gt;
        &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/ssl/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/ssl/privkey.pem&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="c1"&gt;# Forward request to the upstream pool&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://backend_servers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;# Preserve original host and client IP&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;# Enable session persistence using cookies&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_cookie_path&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="s"&gt;"/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;HttpOnly"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;# Timeout settings for reliability&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_connect_timeout&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_send_timeout&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_read_timeout&lt;/span&gt; &lt;span class="s"&gt;10s&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation of key directives&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;upstream backend_servers&lt;/code&gt; defines the pool of servers.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;least_conn&lt;/code&gt; activates the Least Connections algorithm.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;weight=3&lt;/code&gt; gives app-server-1 three times more traffic than app-server-3.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_fails=3 fail_timeout=30s&lt;/code&gt; removes a server after three consecutive failures for 30 seconds.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;proxy_pass http://backend_servers&lt;/code&gt; forwards traffic to the chosen server.&lt;/li&gt;
&lt;li&gt;Header directives ensure the backend knows the original client information.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Advanced Load Balancing Concepts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Consistent Hashing&lt;/strong&gt; is often combined with &lt;strong&gt;load balancing&lt;/strong&gt; to minimize disruption when servers are added or removed. Instead of rehashing everything, only a small portion of traffic is affected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global Server Load Balancing (GSLB)&lt;/strong&gt; extends the concept across multiple data centers using DNS-based routing (Anycast or GeoDNS) to direct users to the nearest healthy region.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto-scaling integration&lt;/strong&gt; allows the &lt;strong&gt;load balancer&lt;/strong&gt; to dynamically register new instances launched by Kubernetes Horizontal Pod Autoscaler or AWS Auto Scaling Groups.&lt;/p&gt;

&lt;p&gt;If you found this deep dive into &lt;strong&gt;load balancing&lt;/strong&gt; valuable and want to master the remaining 99 system design concepts with equally detailed explanations, code examples, and diagrams, grab the complete System Design eBook at &lt;a href="https://codewithdhanian.gumroad.com/l/urcjee" rel="noopener noreferrer"&gt;https://codewithdhanian.gumroad.com/l/urcjee&lt;/a&gt;. You can also support the creation of more high-quality technical content by buying me a coffee at &lt;a href="https://ko-fi.com/codewithdhanian" rel="noopener noreferrer"&gt;https://ko-fi.com/codewithdhanian&lt;/a&gt;.&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%2F55d08ru8tyxz54bg1a4r.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%2F55d08ru8tyxz54bg1a4r.png" alt="Understanding load balancing concepts" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Retry &amp; Exponential Backoff in System Design</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Sun, 05 Apr 2026 10:17:33 +0000</pubDate>
      <link>https://dev.to/code_2/retry-exponential-backoff-in-system-design-3ho6</link>
      <guid>https://dev.to/code_2/retry-exponential-backoff-in-system-design-3ho6</guid>
      <description>&lt;p&gt;In &lt;strong&gt;distributed systems&lt;/strong&gt; and &lt;strong&gt;microservices architectures&lt;/strong&gt;, transient failures are common. Network glitches, temporary service overloads, brief database contention, or momentary unavailability of third-party APIs frequently resolve themselves within seconds. The &lt;strong&gt;Retry&lt;/strong&gt; mechanism combined with &lt;strong&gt;Exponential Backoff&lt;/strong&gt; provides a fundamental resilience strategy that intelligently re-attempts failed operations instead of failing immediately. This pattern significantly improves overall system reliability and user experience by handling flaky conditions gracefully without overwhelming the failing service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retry &amp;amp; Exponential Backoff&lt;/strong&gt; forms one of the core building blocks of fault-tolerant design, often used alongside the &lt;strong&gt;Circuit Breaker Pattern&lt;/strong&gt;, &lt;strong&gt;timeouts&lt;/strong&gt;, &lt;strong&gt;idempotency&lt;/strong&gt;, and &lt;strong&gt;bulkhead isolation&lt;/strong&gt;. When implemented correctly, it reduces unnecessary errors while protecting downstream services from retry storms that could lead to cascading failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Retry Mechanisms
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;retry&lt;/strong&gt; is simply the act of re-executing a failed operation after a short delay. Not every failure deserves a retry. Only &lt;strong&gt;idempotent&lt;/strong&gt; operations or those that are safe to repeat should be retried. Non-idempotent operations require careful handling, often through &lt;strong&gt;idempotency keys&lt;/strong&gt; or unique transaction identifiers to prevent duplicate effects.&lt;/p&gt;

&lt;p&gt;Common transient failure scenarios suitable for retries include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network timeouts or connection resets&lt;/li&gt;
&lt;li&gt;HTTP 503 Service Unavailable or 429 Too Many Requests&lt;/li&gt;
&lt;li&gt;Temporary database deadlocks or lock contention&lt;/li&gt;
&lt;li&gt;Rate limiting responses from external services&lt;/li&gt;
&lt;li&gt;Brief unavailability during scaling events or deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Permanent failures such as validation errors (HTTP 400), authentication failures (401/403), or business logic errors should not trigger retries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exponential Backoff Strategy
&lt;/h2&gt;

&lt;p&gt;Simple fixed-delay retries can create &lt;strong&gt;thundering herd&lt;/strong&gt; problems where many clients retry simultaneously, overwhelming the recovering service. &lt;strong&gt;Exponential Backoff&lt;/strong&gt; solves this by increasing the wait time between retries exponentially. The delay typically follows the formula:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;delay = base_delay × 2^retry_attempt&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To prevent synchronization of retries across clients, &lt;strong&gt;jitter&lt;/strong&gt; (random variation) is added to the calculated delay.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full delay formula with jitter&lt;/strong&gt;:&lt;br&gt;
&lt;strong&gt;delay = min(cap, base_delay × 2^retry_attempt) + random(0, jitter)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Common variations include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full Jitter&lt;/strong&gt;: Random delay between 0 and the computed exponential value&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Equal Jitter&lt;/strong&gt;: Computed delay minus a random portion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decorrelated Jitter&lt;/strong&gt;: Next delay based on previous delay with randomness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Exponential Backoff with Jitter&lt;/strong&gt; dramatically improves system stability under load by spreading retry attempts over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detailed Implementation of Retry with Exponential Backoff
&lt;/h2&gt;

&lt;p&gt;Production-grade implementations must handle concurrency safely, respect maximum retry limits, support different backoff strategies, and integrate with logging and monitoring.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pseudocode for Retry with Exponential Backoff
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class RetryWithBackoff {
    int maxAttempts;
    long baseDelayMs;
    long maxDelayMs;
    double jitterFactor;

    Object executeWithRetry(Callable operation) {
        Exception lastException;

        for (int attempt = 0; attempt &amp;lt; maxAttempts; attempt++) {
            try {
                return operation.call();
            } catch (TransientException e) {
                lastException = e;
                if (attempt == maxAttempts - 1) {
                    break;  // Final attempt failed
                }
                long delay = calculateDelay(attempt);
                sleep(delay);
            } catch (PermanentException e) {
                throw e;  // Do not retry
            }
        }
        throw lastException;  // Propagate after exhausting retries
    }

    private long calculateDelay(int attempt) {
        long exponentialDelay = baseDelayMs * (1L &amp;lt;&amp;lt; attempt);  // 2^attempt
        long cappedDelay = min(exponentialDelay, maxDelayMs);

        // Add full jitter
        long jitter = random(0, (long)(cappedDelay * jitterFactor));
        return cappedDelay + jitter;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Complete Python Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TransientError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retry_with_exponential_backoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;base_delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# 100ms
&lt;/span&gt;    &lt;span class="n"&gt;max_delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# 10 seconds
&lt;/span&gt;    &lt;span class="n"&gt;jitter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;backoff_factor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;last_exception&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;last_exception&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;

                    &lt;span class="c1"&gt;# Check if error is transient (custom logic)
&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;is_transient_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                        &lt;span class="k"&gt;raise&lt;/span&gt;  &lt;span class="c1"&gt;# Permanent error - do not retry
&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;max_attempts&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;span class="k"&gt;break&lt;/span&gt;  &lt;span class="c1"&gt;# Last attempt failed
&lt;/span&gt;
                    &lt;span class="c1"&gt;# Calculate exponential backoff
&lt;/span&gt;                    &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base_delay&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backoff_factor&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;jitter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 10% jitter
&lt;/span&gt;
                    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                    &lt;span class="c1"&gt;# Optional: log retry attempt
&lt;/span&gt;                    &lt;span class="c1"&gt;# logger.warning(f"Retry {attempt+1}/{max_attempts} after {delay:.2f}s")
&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;last_exception&lt;/span&gt;  &lt;span class="c1"&gt;# Re-raise after all retries exhausted
&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;decorator&lt;/span&gt;

&lt;span class="c1"&gt;# Example usage
&lt;/span&gt;&lt;span class="nd"&gt;@retry_with_exponential_backoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_external_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Simulate network call that may fail transiently
&lt;/span&gt;    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.example.com/users/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Java Conceptual Structure (Resilience4j Style)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;RetryConfig&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RetryConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;custom&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxAttempts&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;waitDuration&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofMillis&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;retryOnException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;TransientException&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;intervalFunction&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IntervalFunction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofExponentialBackoff&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;Retry&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Retry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"externalService"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Callable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;retryableCall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Retry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decorateCallable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retry&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;callExternalService&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Try&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofCallable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retryableCall&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recover&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fallbackResponse&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These implementations demonstrate key elements: configurable attempt limits, proper classification of transient versus permanent errors, exponential delay calculation, jitter for load distribution, and clean separation of concerns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Retry &amp;amp; Exponential Backoff
&lt;/h2&gt;

&lt;p&gt;Effective use of this pattern requires attention to several critical details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Idempotency&lt;/strong&gt;: Always ensure retried operations are idempotent or use &lt;strong&gt;idempotency keys&lt;/strong&gt; (unique request identifiers stored server-side) to prevent duplicate side effects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeout Integration&lt;/strong&gt;: Combine retries with appropriate per-attempt timeouts to avoid hanging requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circuit Breaker Synergy&lt;/strong&gt;: Use &lt;strong&gt;circuit breakers&lt;/strong&gt; to stop retries entirely when a service is confirmed unhealthy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring &amp;amp; Observability&lt;/strong&gt;: Track retry counts, success-after-retry rates, and backoff delays using tools like &lt;strong&gt;Prometheus&lt;/strong&gt; and &lt;strong&gt;Grafana&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maximum Delay Caps&lt;/strong&gt;: Prevent excessively long waits by capping delays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client-Specific Backoff&lt;/strong&gt;: Different clients or services may need tailored backoff parameters based on their importance and load characteristics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Retry Storms&lt;/strong&gt;: Jitter and randomized delays are essential in large-scale systems with thousands of instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;strong&gt;event-driven architectures&lt;/strong&gt; using &lt;strong&gt;message queues&lt;/strong&gt; like &lt;strong&gt;Kafka&lt;/strong&gt; or &lt;strong&gt;RabbitMQ&lt;/strong&gt;, retries are often handled through dead-letter queues and delayed message redelivery rather than in-process loops.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Considerations
&lt;/h2&gt;

&lt;p&gt;In high-scale systems, &lt;strong&gt;Retry &amp;amp; Exponential Backoff&lt;/strong&gt; must be applied judiciously. Overly aggressive retries can still contribute to overload. Many modern service meshes (such as Istio) and API gateways provide built-in retry capabilities at the infrastructure layer, allowing application code to focus on business logic.&lt;/p&gt;

&lt;p&gt;The combination of &lt;strong&gt;Retry&lt;/strong&gt; with &lt;strong&gt;Exponential Backoff&lt;/strong&gt; remains one of the simplest yet most powerful techniques for improving resilience in &lt;strong&gt;distributed systems&lt;/strong&gt;. When paired with proper &lt;strong&gt;idempotency&lt;/strong&gt;, &lt;strong&gt;timeouts&lt;/strong&gt;, and &lt;strong&gt;circuit breakers&lt;/strong&gt;, it enables applications to withstand transient issues while maintaining high availability and responsive user experiences.&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%2Fxi5lybmdphpwrqwimj57.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%2Fxi5lybmdphpwrqwimj57.png" alt="Retry with Exponential Backoff" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System Design Handbook&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For more in-depth insights and comprehensive coverage of system design topics, consider purchasing the System Design Handbook at &lt;a href="https://codewithdhanian.gumroad.com/l/ntmcf" rel="noopener noreferrer"&gt;https://codewithdhanian.gumroad.com/l/ntmcf&lt;/a&gt;. It will equip you with the knowledge to master complex distributed systems.  &lt;/p&gt;

&lt;p&gt;Buy me coffee to support my content at: &lt;a href="https://ko-fi.com/codewithdhanian" rel="noopener noreferrer"&gt;https://ko-fi.com/codewithdhanian&lt;/a&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Circuit Breaker Pattern in System Design</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Fri, 03 Apr 2026 08:07:13 +0000</pubDate>
      <link>https://dev.to/code_2/circuit-breaker-pattern-in-system-design-4l24</link>
      <guid>https://dev.to/code_2/circuit-breaker-pattern-in-system-design-4l24</guid>
      <description>&lt;p&gt;In &lt;strong&gt;distributed systems&lt;/strong&gt; and &lt;strong&gt;microservices architectures&lt;/strong&gt;, failures are inevitable. Network latency, service overload, database slowdowns, or third-party API outages can quickly cascade into widespread system instability. The &lt;strong&gt;Circuit Breaker Pattern&lt;/strong&gt; serves as a critical &lt;strong&gt;resilience&lt;/strong&gt; mechanism that prevents these cascading failures by intelligently isolating faulty components. Inspired by electrical circuit breakers that interrupt current flow during overloads, the software version acts as a protective proxy around remote calls, allowing systems to fail fast, degrade gracefully, and recover automatically.&lt;/p&gt;

&lt;p&gt;This pattern is essential for building robust, highly available applications where services depend on each other across network boundaries. By monitoring failure rates and response times, the &lt;strong&gt;circuit breaker&lt;/strong&gt; stops repeated attempts to reach an unhealthy service, giving it time to recover while providing immediate feedback or fallback responses to callers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Circuit Breaker Pattern
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Circuit Breaker Pattern&lt;/strong&gt; functions as a stateful wrapper around operations that interact with external services or resources. Instead of allowing every request to reach a failing downstream service—which could overwhelm it further and degrade the entire system—the &lt;strong&gt;circuit breaker&lt;/strong&gt; tracks metrics such as error counts, latency, or exceptions. When failure thresholds are breached, it “trips” and redirects traffic away from the problematic service.&lt;/p&gt;

&lt;p&gt;Key benefits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prevention of &lt;strong&gt;cascading failures&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Reduction in resource consumption on both caller and callee sides&lt;/li&gt;
&lt;li&gt;Faster response times through immediate failure detection&lt;/li&gt;
&lt;li&gt;Graceful degradation via &lt;strong&gt;fallback mechanisms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Automatic recovery without manual intervention&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern works best when combined with complementary techniques such as &lt;strong&gt;retries with exponential backoff&lt;/strong&gt;, &lt;strong&gt;timeouts&lt;/strong&gt;, &lt;strong&gt;rate limiting&lt;/strong&gt;, and &lt;strong&gt;bulkhead isolation&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three States of a Circuit Breaker
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;circuit breaker&lt;/strong&gt; maintains one of three distinct states, each dictating how incoming requests are handled. These states form a finite state machine that transitions based on observed behavior and configurable thresholds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Closed State&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
This is the normal operating state. All requests pass through to the protected service. The &lt;strong&gt;circuit breaker&lt;/strong&gt; monitors outcomes, counting failures within a sliding time window or consecutive failure count. If the failure rate or count exceeds a predefined threshold (for example, 50% errors in the last 10 seconds or 5 consecutive failures), the breaker transitions to the &lt;strong&gt;Open&lt;/strong&gt; state. Successes reset or decrement failure counters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open State&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
When the circuit is &lt;strong&gt;open&lt;/strong&gt;, the breaker immediately rejects all requests without forwarding them to the downstream service. This prevents further load on the failing component and avoids long timeouts or resource exhaustion. Instead, the caller receives an immediate exception or a &lt;strong&gt;fallback&lt;/strong&gt; response. A timeout timer (reset timeout) starts, after which the breaker moves to the &lt;strong&gt;Half-Open&lt;/strong&gt; state to test recovery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Half-Open State&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
This transitional state allows a limited number of test requests (often just one or a small configurable count) to reach the service. If these probe requests succeed, the &lt;strong&gt;circuit breaker&lt;/strong&gt; assumes recovery and returns to the &lt;strong&gt;Closed&lt;/strong&gt; state, resetting failure counters. If any test fails, the breaker reverts to the &lt;strong&gt;Open&lt;/strong&gt; state and restarts the timeout period. This cautious probing ensures the service has truly stabilized before resuming full traffic.&lt;/p&gt;

&lt;p&gt;These state transitions enable self-healing while protecting system stability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detailed Implementation of the Circuit Breaker Pattern
&lt;/h2&gt;

&lt;p&gt;Implementing a &lt;strong&gt;circuit breaker&lt;/strong&gt; from scratch requires careful handling of concurrency, metrics tracking, and state persistence. In production, developers typically use battle-tested libraries such as &lt;strong&gt;Resilience4j&lt;/strong&gt; (Java), &lt;strong&gt;Hystrix&lt;/strong&gt; (legacy Java), &lt;strong&gt;Polly&lt;/strong&gt; (.NET), or &lt;strong&gt;pybreaker&lt;/strong&gt; (Python). Below are complete, illustrative code structures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pseudocode for a Generic Circuit Breaker
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CircuitBreaker {
    enum State { CLOSED, OPEN, HALF_OPEN }

    State currentState = CLOSED;
    int failureCount = 0;
    int successCount = 0;
    long lastFailureTime = 0;
    Configuration config;  // failureThreshold, timeout, successThreshold, etc.

    Object execute(Callable operation) {
        if (currentState == OPEN) {
            if (isTimeoutExpired()) {
                transitionTo(HALF_OPEN);
            } else {
                return invokeFallback();  // or throw CircuitOpenException
            }
        }

        try {
            Object result = operation.call();
            onSuccess();
            return result;
        } catch (Exception e) {
            onFailure(e);
            return invokeFallback();
        }
    }

    private void onSuccess() {
        failureCount = 0;
        successCount++;
        if (currentState == HALF_OPEN &amp;amp;&amp;amp; successCount &amp;gt;= config.successThreshold) {
            transitionTo(CLOSED);
        }
    }

    private void onFailure(Exception e) {
        failureCount++;
        lastFailureTime = currentTime();
        if (failureCount &amp;gt;= config.failureThreshold || currentState == HALF_OPEN) {
            transitionTo(OPEN);
        }
    }

    private boolean isTimeoutExpired() {
        return (currentTime() - lastFailureTime) &amp;gt; config.resetTimeout;
    }

    private void transitionTo(State newState) {
        currentState = newState;
        // Log state change, notify monitoring system
        if (newState == HALF_OPEN) {
            successCount = 0;
        }
    }

    private Object invokeFallback() {
        // Execute fallback logic, e.g., return cached data or default value
        return defaultResponse();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Java Example Using Resilience4j Style (Conceptual Full Structure)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Configuration&lt;/span&gt;
&lt;span class="nc"&gt;CircuitBreakerConfig&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreakerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;custom&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;failureRateThreshold&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;// Open if failure rate &amp;gt; 50%&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;waitDurationInOpenState&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;// Reset timeout&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;permittedNumberOfCallsInHalfOpenState&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;// Test calls&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;slidingWindowSize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;              &lt;span class="c1"&gt;// Window for metrics&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt; &lt;span class="n"&gt;circuitBreaker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"paymentService"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Decorator usage&lt;/span&gt;
&lt;span class="nc"&gt;Supplier&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;decoratedSupplier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decorateSupplier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;circuitBreaker&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
    &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;callPaymentService&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;// remote call&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// With fallback&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Try&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSupplier&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoratedSupplier&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recover&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;throwable&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fallbackPaymentResponse&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Python Example Using a Simple Custom Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CircuitState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;CLOSED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;closed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;OPEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;HALF_OPEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;half_open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;failure_threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reset_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;success_threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CircuitState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLOSED&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failure_threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;failure_threshold&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reset_timeout&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;success_threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;success_threshold&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failure_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;success_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_failure_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CircuitState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OPEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_failure_time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CircuitState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HALF_OPEN&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;success_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreakerOpenException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Circuit breaker is OPEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;try&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="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_on_success&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_on_failure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;  &lt;span class="c1"&gt;# or handle with fallback
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_on_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failure_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;success_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CircuitState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HALF_OPEN&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;success_count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;success_threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CircuitState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLOSED&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_on_failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failure_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_failure_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failure_count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failure_threshold&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CircuitState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HALF_OPEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CircuitState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OPEN&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreakerOpenException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These implementations highlight essential elements: configurable thresholds, state management, fallback execution, and safe transitions. In real systems, thread-safety (using locks or atomic operations) and integration with monitoring tools like &lt;strong&gt;Prometheus&lt;/strong&gt; are mandatory.&lt;/p&gt;

&lt;h2&gt;
  
  
  When and How to Use the Circuit Breaker Pattern
&lt;/h2&gt;

&lt;p&gt;Apply the &lt;strong&gt;Circuit Breaker Pattern&lt;/strong&gt; to any synchronous or asynchronous call to external services, databases, or third-party APIs where failure could propagate. Common scenarios include &lt;strong&gt;microservices&lt;/strong&gt; communication, payment gateways, inventory checks, or recommendation engines.&lt;/p&gt;

&lt;p&gt;Best practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Combine with &lt;strong&gt;timeouts&lt;/strong&gt; to avoid indefinite waits.&lt;/li&gt;
&lt;li&gt;Implement meaningful &lt;strong&gt;fallbacks&lt;/strong&gt;—cached data, default values, or queued operations.&lt;/li&gt;
&lt;li&gt;Monitor state transitions and metrics for observability.&lt;/li&gt;
&lt;li&gt;Tune thresholds based on service characteristics and traffic patterns.&lt;/li&gt;
&lt;li&gt;Ensure &lt;strong&gt;idempotency&lt;/strong&gt; for operations that may be retried.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern shines in high-traffic environments but adds slight overhead in normal operation due to metric collection. For extremely latency-sensitive paths, evaluate whether the protection justifies the cost.&lt;/p&gt;

&lt;p&gt;Mastering the &lt;strong&gt;Circuit Breaker Pattern&lt;/strong&gt; equips system designers with a powerful tool to build resilient, fault-tolerant distributed systems that maintain availability even when individual components fail.&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%2Fmb2zr7xrho642c7ufv56.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%2Fmb2zr7xrho642c7ufv56.png" alt="Circuit breaker pattern diagram in design" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System Design Handbook&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For more in-depth insights and comprehensive coverage of system design topics, consider purchasing the System Design Handbook at &lt;a href="https://codewithdhanian.gumroad.com/l/ntmcf" rel="noopener noreferrer"&gt;https://codewithdhanian.gumroad.com/l/ntmcf&lt;/a&gt;. It will equip you with the knowledge to master complex distributed systems.  &lt;/p&gt;

&lt;p&gt;Buy me coffee to support my content at: &lt;a href="https://ko-fi.com/codewithdhanian" rel="noopener noreferrer"&gt;https://ko-fi.com/codewithdhanian&lt;/a&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Rate Limiting &amp; Throttling in System Design</title>
      <dc:creator>CodeWithDhanian</dc:creator>
      <pubDate>Fri, 03 Apr 2026 07:54:26 +0000</pubDate>
      <link>https://dev.to/code_2/rate-limiting-throttling-in-system-design-3o83</link>
      <guid>https://dev.to/code_2/rate-limiting-throttling-in-system-design-3o83</guid>
      <description>&lt;p&gt;In large-scale &lt;strong&gt;distributed systems&lt;/strong&gt; and &lt;strong&gt;microservices&lt;/strong&gt; architectures, uncontrolled incoming traffic can quickly lead to resource exhaustion, degraded performance, or complete service outages. &lt;strong&gt;Rate limiting&lt;/strong&gt; and &lt;strong&gt;throttling&lt;/strong&gt; serve as critical defensive mechanisms that protect backend services, ensure fair usage among clients, prevent abuse, and maintain overall system stability under varying load conditions. These techniques control the flow of requests to APIs, databases, or other resources, allowing systems to operate reliably even during traffic spikes or malicious attacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Rate Limiting
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt; is a technique that enforces a strict upper bound on the number of requests a client, user, IP address, or API key can make within a defined time window. The primary goals include protecting against &lt;strong&gt;DDoS attacks&lt;/strong&gt;, ensuring &lt;strong&gt;fair resource allocation&lt;/strong&gt;, enforcing &lt;strong&gt;business quotas&lt;/strong&gt;, and preventing any single client from monopolizing shared resources.&lt;/p&gt;

&lt;p&gt;When a request exceeds the allowed limit, the system typically rejects it immediately and returns an &lt;strong&gt;HTTP 429 Too Many Requests&lt;/strong&gt; status code, often accompanied by headers such as &lt;strong&gt;Retry-After&lt;/strong&gt; to inform the client when it may retry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt; operates at multiple layers: at the &lt;strong&gt;API gateway&lt;/strong&gt;, within individual &lt;strong&gt;microservices&lt;/strong&gt;, at the &lt;strong&gt;load balancer&lt;/strong&gt;, or even at the &lt;strong&gt;edge&lt;/strong&gt; using &lt;strong&gt;content delivery networks&lt;/strong&gt;. In &lt;strong&gt;distributed environments&lt;/strong&gt;, the rate limiter must maintain consistent state across multiple nodes, typically using a centralized store such as &lt;strong&gt;Redis&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Throttling
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Throttling&lt;/strong&gt; differs from &lt;strong&gt;rate limiting&lt;/strong&gt; by focusing on controlling the processing speed or flow of requests rather than imposing a hard rejection limit. Instead of outright denying excess requests, &lt;strong&gt;throttling&lt;/strong&gt; slows down, queues, or paces the handling of requests to maintain a steady load on the system.&lt;/p&gt;

&lt;p&gt;While &lt;strong&gt;rate limiting&lt;/strong&gt; answers the question “Is this request allowed?”, &lt;strong&gt;throttling&lt;/strong&gt; addresses “How fast should this request be processed?”. &lt;strong&gt;Throttling&lt;/strong&gt; is particularly useful for smoothing bursty traffic, protecting downstream services with their own rate limits, or gracefully handling temporary overload without dropping legitimate requests.&lt;/p&gt;

&lt;p&gt;Common &lt;strong&gt;throttling&lt;/strong&gt; strategies include introducing artificial delays, queuing requests in &lt;strong&gt;message queues&lt;/strong&gt;, or dynamically reducing the processing rate based on current system metrics such as CPU usage or queue length.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Differences Between Rate Limiting and Throttling
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt; provides a hard cap and immediate rejection for excess requests, making it ideal for quota enforcement and abuse prevention. &lt;strong&gt;Throttling&lt;/strong&gt; prioritizes smoothing traffic and improving user experience by avoiding abrupt denials, often at the cost of increased latency for some requests. Many production systems combine both: &lt;strong&gt;rate limiting&lt;/strong&gt; at the entry point for protection and &lt;strong&gt;throttling&lt;/strong&gt; internally for traffic shaping.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Rate Limiting Algorithms
&lt;/h2&gt;

&lt;p&gt;Several well-established algorithms exist for implementing &lt;strong&gt;rate limiting&lt;/strong&gt;, each offering different trade-offs in terms of burst tolerance, accuracy, memory usage, and implementation complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Bucket Algorithm
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;token bucket&lt;/strong&gt; algorithm is one of the most widely adopted approaches due to its flexibility and ability to handle controlled bursts. It models capacity as a bucket that accumulates &lt;strong&gt;tokens&lt;/strong&gt; at a constant refill rate up to a maximum capacity. Each incoming request consumes one token. If tokens are available, the request is allowed; otherwise, it is rejected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key parameters&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Refill rate&lt;/strong&gt; (r): Tokens added per unit time (e.g., 10 tokens per second).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bucket capacity&lt;/strong&gt; (b): Maximum number of tokens the bucket can hold, determining burst size.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This algorithm allows short bursts up to the bucket capacity while enforcing the long-term average rate. It is particularly suitable for public APIs where users may send occasional bursts of requests after periods of inactivity.&lt;/p&gt;

&lt;h4&gt;
  
  
  Complete Token Bucket Implementation Example Using Redis (Lua Script for Atomicity)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Token Bucket Lua Script for Redis&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;KEYS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;                  &lt;span class="c1"&gt;-- e.g., "rate:limit:user:123"&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tonumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;        &lt;span class="c1"&gt;-- current timestamp in seconds&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;refill_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tonumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;-- tokens per second&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tonumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;   &lt;span class="c1"&gt;-- max bucket size&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;tokens_requested&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tonumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;-- Get current tokens and last refill time&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;last_refill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tonumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"HGET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"last_refill"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tonumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"HGET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"tokens"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;-- Calculate new tokens to add&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;last_refill&lt;/span&gt;
&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;new_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;math.floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;refill_rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;math.min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;new_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;-- Check if enough tokens available&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens_requested&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;tokens_requested&lt;/span&gt;
    &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"HSET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"tokens"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"HSET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"last_refill"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"EXPIRE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;-- expire after 1 hour for cleanup&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;               &lt;span class="c1"&gt;-- allowed, remaining tokens&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;               &lt;span class="c1"&gt;-- rejected, remaining tokens&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;strong&gt;Lua script&lt;/strong&gt; ensures atomic execution, preventing race conditions in &lt;strong&gt;distributed systems&lt;/strong&gt;. The client calls this script via &lt;strong&gt;EVAL&lt;/strong&gt; or &lt;strong&gt;EVALSHA&lt;/strong&gt; commands in Redis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leaky Bucket Algorithm
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;leaky bucket&lt;/strong&gt; algorithm treats requests as water pouring into a bucket with a small hole at the bottom. Requests enter the bucket and are processed (leaked) at a constant fixed rate. If the bucket overflows, incoming requests are rejected or queued.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leaky bucket&lt;/strong&gt; excels at smoothing traffic to a steady output rate, making it ideal for scenarios requiring predictable load, such as payment processing or integration with external services that have strict rate limits. Unlike &lt;strong&gt;token bucket&lt;/strong&gt;, it does not permit large bursts; excess requests are either delayed or dropped.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixed Window Counter Algorithm
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;fixed window&lt;/strong&gt; algorithm divides time into fixed intervals (e.g., one minute or one hour) and counts the number of requests within each window. A counter is incremented for every allowed request. When the counter exceeds the limit for the current window, further requests are rejected until the next window begins.&lt;/p&gt;

&lt;p&gt;This approach is simple and memory-efficient but suffers from the &lt;strong&gt;boundary burst problem&lt;/strong&gt;: clients can send twice the allowed rate at window edges (e.g., 100 requests at the end of one minute and another 100 immediately at the start of the next).&lt;/p&gt;

&lt;h4&gt;
  
  
  Simple Fixed Window Pseudocode
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function isAllowed(clientId, limit, windowSeconds):
    currentWindow = floor(currentTime / windowSeconds)
    counterKey = "rate:" + clientId + ":" + currentWindow
    count = redis.INCR(counterKey)
    if count == 1:
        redis.EXPIRE(counterKey, windowSeconds)
    return count &amp;lt;= limit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sliding Window Algorithms
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Sliding window&lt;/strong&gt; approaches provide higher accuracy by using a continuously moving time frame instead of rigid boundaries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sliding Window Log&lt;/strong&gt;: Maintains a sorted list or set of timestamps for every request made by a client within the window. On each request, remove old timestamps outside the window and check if the remaining count is below the limit. This offers precise control but consumes significant memory for high-traffic clients.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sliding Window Counter&lt;/strong&gt;: A hybrid that combines fixed windows with mathematical adjustment. It tracks counts in the current and previous windows and calculates a weighted count for the sliding period. This balances accuracy and memory usage effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distributed Rate Limiting Considerations
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;microservices&lt;/strong&gt; or multi-node deployments, a single in-memory rate limiter is insufficient. Designers must ensure consistency across instances using a shared &lt;strong&gt;distributed cache&lt;/strong&gt; such as &lt;strong&gt;Redis&lt;/strong&gt;, &lt;strong&gt;Memcached&lt;/strong&gt;, or a dedicated rate-limiting service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistent hashing&lt;/strong&gt; can route requests for the same client to the same shard, while &lt;strong&gt;Lua scripts&lt;/strong&gt; or atomic operations guarantee correctness under concurrency. For extremely high scale, consider &lt;strong&gt;Redis Cluster&lt;/strong&gt; or &lt;strong&gt;consistent hashing&lt;/strong&gt; combined with local caching for hot clients.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Idempotency&lt;/strong&gt; and proper &lt;strong&gt;error handling&lt;/strong&gt; are essential: clients should receive clear &lt;strong&gt;rate limit headers&lt;/strong&gt; (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) to adjust their behavior gracefully.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Implementing Rate Limiting &amp;amp; Throttling
&lt;/h2&gt;

&lt;p&gt;Apply &lt;strong&gt;rate limiting&lt;/strong&gt; at multiple levels: edge (CDN or API gateway), service level, and database level. Choose the algorithm based on requirements — &lt;strong&gt;token bucket&lt;/strong&gt; for burst-tolerant APIs, &lt;strong&gt;leaky bucket&lt;/strong&gt; for traffic shaping, and &lt;strong&gt;sliding window counter&lt;/strong&gt; for strict fairness with good performance.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;Redis&lt;/strong&gt; with &lt;strong&gt;Lua scripts&lt;/strong&gt; for atomicity in distributed setups. Always return informative headers and consider &lt;strong&gt;adaptive rate limiting&lt;/strong&gt; that dynamically adjusts limits based on system load. Combine with &lt;strong&gt;circuit breakers&lt;/strong&gt;, &lt;strong&gt;bulkheads&lt;/strong&gt;, and &lt;strong&gt;monitoring&lt;/strong&gt; (Prometheus, Grafana) to detect and respond to abuse patterns.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;throttling&lt;/strong&gt;, integrate with &lt;strong&gt;message queues&lt;/strong&gt; (Kafka, RabbitMQ) to queue excess requests or apply exponential backoff and jitter on retries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt; and &lt;strong&gt;throttling&lt;/strong&gt; form foundational resilience patterns in &lt;strong&gt;system design&lt;/strong&gt;. Proper implementation protects services, improves user experience, and enables sustainable scaling of &lt;strong&gt;distributed systems&lt;/strong&gt;.&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%2Fvspobzgxoanq63oddaun.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%2Fvspobzgxoanq63oddaun.png" alt="Rate limiting vs throttling comparison" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System Design Handbook&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For more in-depth insights and comprehensive coverage of system design topics, consider purchasing the System Design Handbook at &lt;a href="https://codewithdhanian.gumroad.com/l/ntmcf" rel="noopener noreferrer"&gt;https://codewithdhanian.gumroad.com/l/ntmcf&lt;/a&gt;. It will equip you with the knowledge to master complex distributed systems.  &lt;/p&gt;

&lt;p&gt;Buy me coffee to support my content at: &lt;a href="https://ko-fi.com/codewithdhanian" rel="noopener noreferrer"&gt;https://ko-fi.com/codewithdhanian&lt;/a&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
