<?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: jiisanda🙆‍♂️</title>
    <description>The latest articles on DEV Community by jiisanda🙆‍♂️ (@jiisanda).</description>
    <link>https://dev.to/jiisanda</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%2F1113941%2F35cfc5bf-8a69-4c31-bde2-8e9e01adbf3a.jpeg</url>
      <title>DEV Community: jiisanda🙆‍♂️</title>
      <link>https://dev.to/jiisanda</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jiisanda"/>
    <language>en</language>
    <item>
      <title>Docker Rootless: high security and high performance</title>
      <dc:creator>jiisanda🙆‍♂️</dc:creator>
      <pubDate>Tue, 11 Feb 2025 20:24:24 +0000</pubDate>
      <link>https://dev.to/jiisanda/docker-rootless-high-security-and-high-performance-2ji8</link>
      <guid>https://dev.to/jiisanda/docker-rootless-high-security-and-high-performance-2ji8</guid>
      <description>&lt;p&gt;On installing docker on Ubuntu or Debian system using the following command…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -sSL https://get.docker.com/ | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We might get the following message at the end of the command that says…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;To run Docker as a non-privileged user, consider setting up the
Docker daemon in rootless mode for your user:

    dockerd-rootless-setuptool.sh install

Visit https://docs.docker.com/go/rootless/ to learn about rootless mode.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does that mean?&lt;/p&gt;

&lt;p&gt;By default, Docker requires root privileges to run, as it interacts with system-level components such as Docker daemon and system resources like networking  and storage. However, running Docker as root can pose security risks. &lt;/p&gt;

&lt;p&gt;To mitigate these risks and allow non-privileged users to run Docker without granting them root access, Docker introduced a feature called “rootless mode”. In rootless mode, the Docker daemon and containers run entirely within the user’s own namespace, without needing root privileges. In this article, we will explore how Rootless mode works, setting up, advantages, limitations and use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 How Rootless mode work?
&lt;/h2&gt;

&lt;p&gt;Docker rootless fundamentally changes the traditional way of running the both Docker daemon and containers as an unprivileged user. This is how it is done:&lt;/p&gt;

&lt;p&gt;First, rootless mode uses user namespace, which is a Linux kernel feature that lets unprivileged users create containers. Inside these namespaces, a user can have privileges that look like root permissions, but these privileges are actually restricted to the namespace. This is the same as having admin rights in a sandbox - we can do administrative tasks, but only within that confined space.&lt;/p&gt;

&lt;p&gt;The rootless mode operates by running the Docker daemon as a regular user process instead of root. This daemon process creates a user namespace where it appears to have root privileges, but these privileges don’t extend outside the namespace.&lt;/p&gt;

&lt;p&gt;Network management becomes interesting in rootless mode. For port binding below &lt;code&gt;1024&lt;/code&gt; (traditionally requiring root), rootless mode can use rootlesskit, which provides an unprivileged port mapping feature. This lets containers bind to privileged ports through user-space root privileges.&lt;/p&gt;

&lt;p&gt;One important technical detail is how &lt;code&gt;subuid&lt;/code&gt; and &lt;code&gt;subgid&lt;/code&gt; mapping work. The system needs to map the user’s UID inside the containers to a range of UIDs on the host system. This mapping is configured in &lt;code&gt;/etc/subuid&lt;/code&gt; and &lt;code&gt;/etc/subgid&lt;/code&gt;, allowing the user namespace to work properly while maintaining security isolation.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟡 Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before setting up Docker in Rootless mode, there are several prerequisites to consider:&lt;/p&gt;

&lt;p&gt;You must install &lt;code&gt;newuidmap&lt;/code&gt; and &lt;code&gt;newgidmap&lt;/code&gt; on the host. These commands are provided by the uidmap package.&lt;br&gt;
For Debian / Ubuntu:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;uidmap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Check Current User’s UID/GID:
&lt;code&gt;/etc/subuid&lt;/code&gt; and &lt;code&gt;/etc/subgid&lt;/code&gt; contains a significant number of subordinate UIDs/GIDs for the user. Let’s verify that:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;
1001
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;whoami
&lt;/span&gt;jiisanda
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; ^&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;: /etc/subuid
jiisanda:231072:65536
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; ^&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;: /etc/subgid
jiisanda:231072:65536
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By verifying these steps, you  ensure that the user running Docker in Rootless mode has a sufficient number of subordinate UIDs/GIDs allocated for proper operation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the &lt;code&gt;dbus-user-session&lt;/code&gt; package:
On Ubuntu, installing the &lt;code&gt;dbus-user-session&lt;/code&gt; package is recommended for proper functioning of certain system services and components. This package provides the D-Bus session bus for user sessions, which can be crucial for running services like Docker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install &lt;code&gt;dbus-user-session&lt;/code&gt; using the following command…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt-get install dbus-user-session
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📥 Install
&lt;/h2&gt;

&lt;p&gt;If the system-wide Docker daemon is already running, consider disabling it:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl disable –now docker.service docker.socket
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo rm&lt;/span&gt; /var/run/docker.sock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If installed Docker 20.10 or later with RPM/DEB packages, it’s a pretty simple set up. You should have &lt;code&gt;docker-rootless-setuptools.sh&lt;/code&gt; in &lt;code&gt;/usr/bin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;dockerd-rootless-setuptool.sh install&lt;/code&gt; as a &lt;strong&gt;non-root&lt;/strong&gt; user to set up the daemon:&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="nv"&gt;$ &lt;/span&gt;dockerd-rootless-setuptool.sh &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;INFO] Creating /home/testuser/.config/systemd/user/docker.service
...
&lt;span class="o"&gt;[&lt;/span&gt;INFO] Installed docker.service successfully.
&lt;span class="o"&gt;[&lt;/span&gt;INFO] To control docker.service, run: &lt;span class="sb"&gt;`&lt;/span&gt;systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;start|stop|restart&lt;span class="o"&gt;)&lt;/span&gt; docker.service&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;INFO] To run docker.service on system startup, run: &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;loginctl enable-linger testuser&lt;span class="sb"&gt;`&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;INFO] Make sure the following environment variables are &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;or add them to ~/.bashrc&lt;span class="o"&gt;)&lt;/span&gt;:

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DOCKER_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;unix:///run/user/1000/docker.sock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;dockerd-rootless-setuptool.sh&lt;/code&gt; is not present, you may need to install the &lt;code&gt;docker-ce-rootless-extras&lt;/code&gt; package manually, as…&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker-ce-rootless-extras
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ✅ Best Practices for using Docker Rootless
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Ensure Your System Meets Requirements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a modern Linux kernel (5.11+ recommended for better performance).&lt;/li&gt;
&lt;li&gt;Install necessary dependencies like &lt;code&gt;uidmap&lt;/code&gt;, &lt;code&gt;slirp4netns&lt;/code&gt;, &lt;code&gt;fuse-overlayfs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;dockerd-rootless-setuptool.sh check&lt;/code&gt; to verify system compatibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use OverlayFS for Better Performance&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By default, fuse-overlayfs is used in rootless mode.&lt;/li&gt;
&lt;li&gt;If your system supports it, enable OverlayFS (&lt;code&gt;--storage-driver=overlay2&lt;/code&gt;) for better disk performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Optimize Networking for Performance&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rootless mode uses slirp4netns for user-space networking, which can be slower.&lt;/li&gt;
&lt;li&gt;If possible, use Host networking (&lt;code&gt;--network=host&lt;/code&gt;) when running containers that require better performance.&lt;/li&gt;
&lt;li&gt;Consider VPNKit or RootlessKit for improved networking options.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use Systemd for Better Stability&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start Docker Rootless with systemd instead of running it manually, this ensures Docker restarts automatically after a system reboot:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="nb"&gt;enable &lt;/span&gt;docker
&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; start docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Limit Resource Usage&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since &lt;strong&gt;Rootless Docker&lt;/strong&gt; runs as a user process, it doesn’t have system-wide privileges.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;cgroups v2&lt;/strong&gt; to set resource limits for CPU, memory, and I/O.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;512m &lt;span class="nt"&gt;--cpus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 my-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enable Logging &amp;amp; Debugging&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check logs to troubleshoot issues, after running the command below run &lt;code&gt;docker info&lt;/code&gt; to verify that Docker is running in rootless mode:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;journalctl &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; docker.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🚀 Use cases for Docker Rootless
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Multi-User Environments (Universities, Research Labs)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows different users to run containers without needing root privileges.&lt;/li&gt;
&lt;li&gt;Prevents one user’s container from affecting another user’s work.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Secure Development Environments&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers can run Docker without risking system security.&lt;/li&gt;
&lt;li&gt;Ideal for isolated testing and running containers on personal machines.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CI/CD Pipelines&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Useful for CI/CD environments where security is a priority.&lt;/li&gt;
&lt;li&gt;No need to grant root access to build agents running Docker.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Shared Hosting &amp;amp; Workstations&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosting providers can allow customers to run Docker containers without exposing the entire system.&lt;/li&gt;
&lt;li&gt;Perfect for corporate workstations where security policies prohibit root access.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Running Containers in Restricted Environments&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you don’t have &lt;code&gt;sudo&lt;/code&gt; access (e.g., cloud-hosted VMs or corporate laptops), rootless mode allows you to use Docker safely.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🚨 When NOT to Use Docker Rootless
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;❌ High-Performance Production Environments&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rootless networking (&lt;code&gt;slirp4netns&lt;/code&gt;) is slower than rootful networking.
Storage performance is slightly lower without direct disk access.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;❌ If You Need Privileged Containers&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rootless Docker cannot run privileged containers (&lt;code&gt;--privileged&lt;/code&gt; flag won’t work).
Containers cannot access low-level hardware (e.g., GPUs, USB devices).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;❌ If You Need System-Wide Networking&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rootless mode does not support port bindings under 1024 (e.g., you can’t expose &lt;code&gt;80:80&lt;/code&gt;).
Workarounds exist (&lt;code&gt;iptables&lt;/code&gt; tricks), but it’s not as flexible as rootful Docker.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker Rootless is a &lt;strong&gt;great choice&lt;/strong&gt; for secure, non-privileged environments like &lt;strong&gt;development&lt;/strong&gt;, &lt;strong&gt;CI/CD&lt;/strong&gt;, and &lt;strong&gt;multi-user systems&lt;/strong&gt;. However, for production workloads requiring high performance, rootful Docker is still the better option.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>linux</category>
      <category>proxy</category>
    </item>
    <item>
      <title>AWS Network Fundamentals for EC2 instance!</title>
      <dc:creator>jiisanda🙆‍♂️</dc:creator>
      <pubDate>Sun, 29 Dec 2024 10:33:32 +0000</pubDate>
      <link>https://dev.to/jiisanda/aws-network-fundamentals-for-ec2-instance-4684</link>
      <guid>https://dev.to/jiisanda/aws-network-fundamentals-for-ec2-instance-4684</guid>
      <description>&lt;p&gt;Have you ever launched an EC2 instance by following a tutorial, blindly inputting values without fully understanding their significance? While it might work at first glance, the magic behind EC2 lies in its networking fundamentals—Virtual Private Clouds (VPCs), subnets, gateways, route tables, and security groups all working together to ensure your instance is both functional and secure.&lt;/p&gt;

&lt;p&gt;In this article, we’ll go beyond surface-level configurations. You’ll gain a clear understanding of the core networking concepts that power AWS EC2. We’ll explore how to create and configure VPCs, set up public and private subnets with appropriate CIDR ranges, manage gateways for connectivity, and secure your network using security groups and Network ACLs.&lt;/p&gt;

&lt;p&gt;To make it even more engaging, we’ll include step-by-step YouTube embeds to show how to configure each component in the AWS Management Console. By the end, you won’t just know how to set up an EC2 instance—you’ll know why each step matters and how it impacts your cloud architecture.&lt;/p&gt;

&lt;p&gt;Let’s dive in and master the backbone of AWS EC2 networking!&lt;/p&gt;

&lt;p&gt;At the starting point we just have a AWS Cloud, so just go to &lt;a href="https://aws.amazon.com" rel="noopener noreferrer"&gt;https://aws.amazon.com&lt;/a&gt; and create your free account. After that we have something called VPCs (Virtual Private Cloud).&lt;/p&gt;

&lt;h3&gt;
  
  
  VPC
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;A VPC is a virtual private cloud, which works like a private network to isolate the resources within it. The solution described in these topics uses an AWS service called Amazon VPC.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's like a fence around a bunch of resources, separating all of the resources within that fence from another VPC.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Vwe0XLUBfsw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here, while creating a VPC, we specified a CIDR of &lt;code&gt;10.0.0.0/16&lt;/code&gt;. But what exactly is a CIDR range, and how do &lt;code&gt;/24&lt;/code&gt; or &lt;code&gt;/16&lt;/code&gt; differ?&lt;/p&gt;

&lt;h4&gt;
  
  
  What is a CIDR Range?
&lt;/h4&gt;

&lt;p&gt;CIDR (Classless Inter-Domain Routing) is a method used to allocate IP addresses efficiently. Instead of using fixed blocks of IPs, CIDR allows for flexible assignment of IP ranges. A CIDR block is expressed as an IP address, followed by a slash (/) and a number indicating how many bits are used for the network prefix.&lt;/p&gt;

&lt;p&gt;For example, in the CIDR 10.0.0.0/16:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;10.0.0.0&lt;/code&gt; is the base IP address.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/16&lt;/code&gt; means that the first 16 bits are reserved for the network portion, leaving the remaining bits for defining individual hosts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  CIDR Block Size and Address Allocation
&lt;/h4&gt;

&lt;p&gt;The number after the slash determines how many IP addresses are available in the range:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/16&lt;/code&gt;: Reserves the first 16 bits for the network. This allows for 2^(32-16) = 65,536 IP addresses, which is suitable for large subnets.
Example: 10.0.0.0 to 10.0.255.255.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/24&lt;/code&gt;: Reserves the first 24 bits, leaving 8 bits for hosts. This provides 2^(32-24) = 256 IP addresses, which is common for smaller manageable subnets (e.g., public and private subnets).
Example: 10.0.0.0 to 10.0.0.255.&lt;/li&gt;
&lt;/ul&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%2Fqj491nksyr3kw0xvaffy.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%2Fqj491nksyr3kw0xvaffy.png" alt="create VPC step" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now within this VPC, we have isolated networks, with different CIDR ranges called subnets. &lt;/p&gt;

&lt;h3&gt;
  
  
  Subnets
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;A subnet is a defined set of network IP addresses that are used to increase the security and efficiency of network communications. You can think of them like postal codes, used for routing packages from one location to another. The Subnets list in the Amazon VPC console displays subnet IDs and also their associated VPC IDs, route tables, and network ACLs. You need to provide at least two subnets in different availability zones to create a VPC connection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A subnet is a range of IP addresses in our VPC. We can create AWS resources, such as EC2 instances, in specific subnets.&lt;/p&gt;

&lt;p&gt;Each subnet must reside within one Availability Zones. By launching AWS resources in different Availability zones, we can protect our application from failure of single zone.&lt;/p&gt;

&lt;p&gt;Normally, for pet projects we can create 2 subnets, a public subnet and a private subnets, with different Availability zone. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Public Subnet&lt;/strong&gt;: The subnet has a direct route to an internet gateway (discussed further). Resources in a public cloud can access the public internet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private Subnet&lt;/strong&gt;: The subnet does not have a direct route to an internet gateway. Resources in a private subnet require a NAT gateway (discussed further) to access the public internet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/SLpk8cmtLRc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;So, following is what we have now: a VPC with two subnets, &lt;strong&gt;PublicSubnet&lt;/strong&gt; and &lt;strong&gt;PrivateSubnet&lt;/strong&gt;. While creating these subnets, we assigned:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PublicSubnet&lt;/strong&gt;: IPv4 CIDR block &lt;code&gt;10.0.0.0/24&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PrivateSubnet&lt;/strong&gt;: IPv4 CIDR block &lt;code&gt;10.0.1.0/24&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Significance of Subnet CIDR Blocks
&lt;/h4&gt;

&lt;p&gt;The CIDR blocks define the range of IP addresses available within each subnet. Here's the breakdown:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PublicSubnet (10.0.0.0/24)&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This subnet can host resources that require internet access.
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;/24&lt;/code&gt; CIDR block means there are &lt;strong&gt;256 available IPs&lt;/strong&gt; (2^8) in this subnet, ranging from &lt;code&gt;10.0.0.0&lt;/code&gt; to &lt;code&gt;10.0.0.255&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;AWS reserves &lt;strong&gt;5 IP addresses&lt;/strong&gt; from this range for internal use, leaving &lt;strong&gt;251 usable IPs&lt;/strong&gt; for EC2 instances and other resources.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PrivateSubnet (10.0.1.0/24)&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This subnet is meant for resources that don’t need direct internet access, such as databases or internal services.
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;/24&lt;/code&gt; CIDR block provides another &lt;strong&gt;256 IPs&lt;/strong&gt;, ranging from &lt;code&gt;10.0.1.0&lt;/code&gt; to &lt;code&gt;10.0.1.255&lt;/code&gt;, with &lt;strong&gt;251 usable IPs&lt;/strong&gt; after AWS reservations.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By assigning distinct CIDR blocks to each subnet, we ensure that:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources in the &lt;strong&gt;PublicSubnet&lt;/strong&gt; and &lt;strong&gt;PrivateSubnet&lt;/strong&gt; don’t overlap or conflict.
&lt;/li&gt;
&lt;li&gt;We maintain clear separation for routing and security purposes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Recap of Our Current Setup
&lt;/h4&gt;

&lt;p&gt;We now have:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;strong&gt;VPC&lt;/strong&gt; with a CIDR range of &lt;code&gt;10.0.0.0/16&lt;/code&gt;, giving us up to 65,536 IP addresses.
&lt;/li&gt;
&lt;li&gt;Two subnets within this VPC:

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;PublicSubnet&lt;/strong&gt; (&lt;code&gt;10.0.0.0/24&lt;/code&gt;) for internet-facing resources.
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;PrivateSubnet&lt;/strong&gt; (&lt;code&gt;10.0.1.0/24&lt;/code&gt;) for internal resources.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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%2Fojy5auldkzot6ej8lo1l.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%2Fojy5auldkzot6ej8lo1l.png" alt="Public Private Subnet" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we are going to launch an EC2 instance into our public subnet. &lt;/p&gt;

&lt;h3&gt;
  
  
  Launching Public EC2
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/BIxwDBIHrBw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;So, we launched the instance with basic configurations: naming it, selecting the AMI, choosing the instance type, and creating a key-pair for secure access. Then, in the Network Settings, we selected the VPC and public subnet we created earlier. To ensure our instance could communicate with the internet, we enabled public IP generation.&lt;/p&gt;

&lt;p&gt;Next, we configured the Security Group, which acts as a virtual firewall for our instance to control incoming and outgoing traffic. We allowed SSH traffic (port 22) in the Security Group, which enables us to connect to the instance using our key-pair securely from our local machine.&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%2F4s44y5p6o9k702eplowo.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%2F4s44y5p6o9k702eplowo.png" alt="Launching Public EC2 - with error" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  But Wait, Was That Enough?
&lt;/h4&gt;

&lt;p&gt;No! We encountered an error while trying to connect to our EC2 instance. This happened because our VPC doesn’t yet have an Internet Gateway (IGW). An IGW is essential to allow internet communication for resources within a public subnet. Without it, even instances with public IPs cannot connect to the internet.&lt;/p&gt;

&lt;h4&gt;
  
  
  What's Next?
&lt;/h4&gt;

&lt;p&gt;Now, let’s resolve this issue!&lt;br&gt;
We’ll add an Internet Gateway to our VPC to enable connectivity for our PublicSubnet. &lt;/p&gt;
&lt;h3&gt;
  
  
  Gateway
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;A gateway connects your VPC to another network. Example, An internet gateway is a VPC component that allows communication between instances in your VPC and the internet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Internet Gateway acts as a doorway, allowing traffic to flow between the internet and the instances in our public subnet. However, simply attaching the Internet Gateway to our VPC isn’t enough—we also need to provide a route for traffic to reach the gateway.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Iu82LAOQldU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In the video, we successfully created an Internet Gateway and attached it to our VPC. Note: A VPC can only have one Internet Gateway at a time.&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%2F8tcgh4pxkf8wq5t733v1.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%2F8tcgh4pxkf8wq5t733v1.png" alt="Internet Gateway - error" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  But Wait, Why Can’t We Connect Yet?
&lt;/h4&gt;

&lt;p&gt;Even though the Internet Gateway is attached, the public subnet doesn’t know how to send traffic to the gateway. This happens because the Route Table associated with the subnet doesn’t include a route to the Internet Gateway. Without this, traffic to and from the internet has no defined path, leaving our instance unreachable.&lt;/p&gt;

&lt;h4&gt;
  
  
  What's Next?
&lt;/h4&gt;

&lt;p&gt;Let’s fix this by updating the Route Table associated with our PublicSubnet. We’ll add a route to the Internet Gateway, enabling traffic to flow between the internet and our EC2 instance seamlessly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Route Table
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;A route table contains a set of rules, called routes, that are used to determine where network traffic is directed. You can view the route table in the Amazon VPC console at &lt;a href="https://console.aws.amazon.com/vpc/" rel="noopener noreferrer"&gt;https://console.aws.amazon.com/vpc/&lt;/a&gt;. The VPC details display the route table that the VPC is using. You can also see Route tables listed in the Amazon VPC console.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Q1XwEKyBPEQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Think of a route table as a &lt;em&gt;GPS system&lt;/em&gt; for your network traffic. It helps direct traffic to its intended destination, whether it’s within the VPC or outside to the internet.&lt;/p&gt;

&lt;p&gt;In the VPC dashboard, under the "Route Table" section, you’ll notice that your VPC comes with a default Route Table—referred to as the main Route Table. This is used by all unassociated subnets by default.&lt;/p&gt;

&lt;p&gt;The local route (&lt;code&gt;10.0.0.0/16&lt;/code&gt;) in this table allows communication between resources within the VPC, such as the public and private subnets. However, it doesn’t direct traffic outside the VPC.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating Separate Route Tables
&lt;/h4&gt;

&lt;p&gt;By default, both public and private subnets use the main Route Table. To ensure proper isolation and functionality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a dedicated Route Table for the public subnet.&lt;/li&gt;
&lt;li&gt;Create another Route Table for the private subnet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation ensures public resources can communicate with the internet, while private resources remain secure and isolated.&lt;/p&gt;

&lt;h4&gt;
  
  
  Associating and Adding Routes
&lt;/h4&gt;

&lt;p&gt;After creating the Route Tables, associate each table with its corresponding subnet—PublicSubnet and PrivateSubnet.&lt;/p&gt;

&lt;p&gt;For the PublicSubnet Route Table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a route with the following details:

&lt;ul&gt;
&lt;li&gt;Destination: 0.0.0.0/0 (all internet traffic).&lt;/li&gt;
&lt;li&gt;Target: Internet Gateway (IGW).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Save the changes, and now your public subnet has internet connectivity!&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%2Fgbgcfshuu6gpb5bfuwa8.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%2Fgbgcfshuu6gpb5bfuwa8.png" alt="Route Table" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Success!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And just like that, our EC2 instance is connected to the internet. Now, we can SSH into it, update packages, and configure it further directly from the shell. Let’s launch an EC2 instance into our private subnet. &lt;/p&gt;

&lt;h3&gt;
  
  
  Private Instance and NAT Gateways
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/7TH0kZWetpc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;So, for the private subnet, we created another EC2 instance. While doing so, we selected the same VPC and ensured the instance was launched in the private subnet. We successfully connected to the private instance using SSH from the public instance, thanks to the route table configurations. Also, don’t forget to have your &lt;code&gt;.pem&lt;/code&gt; file in the public instance with the correct permissions (&lt;code&gt;chmod 400&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;However, once inside the private instance, when we tried to update the packages, we encountered an issue—our private instance couldn’t access the internet. Why? Because the private subnet is isolated from direct internet access for security reasons.&lt;/p&gt;

&lt;p&gt;Here’s where the NAT Gateway comes into play.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A NAT gateway is a Network Address Translation (NAT) service. You can use a NAT gateway so that instances in a private subnet can connect to services outside your VPC but external services cannot initiate a connection with those instances.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Think of it as your instance requesting updates or connecting to an external API—your NAT Gateway makes the request on behalf of your private instance, retrieves the response, and passes it back to the instance. This ensures your private subnet remains shielded from any unsolicited access.&lt;/p&gt;

&lt;p&gt;Here are a few suggestions to refine and enhance your explanation about NAT Gateway and its role in enabling secure internet access for private subnets:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Nt7zokywBUc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;After creating our NAT Gateway in the public subnet, we configured the private subnet’s route table to direct outbound traffic to the NAT Gateway. Here’s how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Why the NAT Gateway is in the Public Subnet&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The NAT Gateway itself needs internet access to route outbound traffic from the private subnet. By placing it in the public subnet, it can utilize the internet gateway already configured for public internet access.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Routing the Private Subnet through the NAT Gateway&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We updated the &lt;strong&gt;Private Route Table&lt;/strong&gt; to include a new route:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Destination&lt;/strong&gt;: &lt;code&gt;0.0.0.0/0&lt;/code&gt; (all internet traffic)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target&lt;/strong&gt;: The NAT Gateway ID&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;This ensures all outbound traffic from the private subnet destined for the internet is routed via the NAT Gateway.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Testing the Connection&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After updating the route table, we SSH’d into the private instance using the public instance as a jump host.&lt;/li&gt;
&lt;li&gt;We then successfully ran package updates (&lt;code&gt;sudo yum update -y&lt;/code&gt; or &lt;code&gt;sudo apt update&lt;/code&gt;), confirming that the private instance could access the internet.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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%2F0fd8zbn4v13nzdjdfetu.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%2F0fd8zbn4v13nzdjdfetu.png" alt="Private Instance and NAT Gateway" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  NACLs and Security Group
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;A network access control list (ACL) allows or denies specific inbound or outbound traffic at the subnet level. You can use the default network ACL for your VPC, or you can create a custom network ACL for your VPC with rules that are similar to the rules for your security groups in order to add an additional layer of security to your VPC.&lt;/p&gt;

&lt;p&gt;A security group is a set of rules that controls the network access to the resources it is associated with. Access is permitted only to and from the components defined in the security group's inbound and outbound rules. If no rules are defined, the security group prevents all access. You can view security groups from several different consoles, depending on which resource that a particular security group applies to. You can see all the security groups and their settings in one place in the VPC console. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The network is configured securely, and we understand the significance of each component in making this work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary of What We've Accomplished:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;VPC Creation&lt;/strong&gt;: We built a secure Virtual Private Cloud with a CIDR range of &lt;code&gt;10.0.0.0/16&lt;/code&gt;, capable of hosting up to 65,536 IPs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subnet Configuration&lt;/strong&gt;: Divided the VPC into two subnets:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PublicSubnet&lt;/strong&gt; for internet-facing resources (&lt;code&gt;10.0.0.0/24&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PrivateSubnet&lt;/strong&gt; for internal resources (&lt;code&gt;10.0.1.0/24&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internet Gateway Setup&lt;/strong&gt;: Attached an Internet Gateway to our VPC to allow internet traffic for public resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route Table Management&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Configured a custom Route Table for the PublicSubnet with a route to the Internet Gateway for internet connectivity.&lt;/li&gt;
&lt;li&gt;Left the PrivateSubnet secured without a direct route to the internet.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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%2Fjjmhxf2rhe5ts5cvyabd.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%2Fjjmhxf2rhe5ts5cvyabd.png" alt="AWS Network Fundamentals" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Understanding the networking fundamentals is a game-changer when working with AWS. It transforms the process of launching an EC2 instance from a simple "trial and error" into a deliberate and well-architected solution. By mastering these principles, you're not just deploying applications—you’re building robust, scalable, and secure cloud architectures.&lt;/p&gt;

&lt;p&gt;Let me know if you'd like to dive deeper into any of these concepts or explore additional AWS networking components like NAT Gateways, VPNs, or security best practices!&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docs: &lt;a href="https://docs.aws.amazon.com/quicksight/latest/user/vpc-terminology.html" rel="noopener noreferrer"&gt;VPC terminology&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html" rel="noopener noreferrer"&gt;Amazon VPC&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;YouTube: &lt;a href="https://www.youtube.com/watch?v=hiKPPy584Mg" rel="noopener noreferrer"&gt;AWS Networking Fundamentals&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>network</category>
      <category>ec2</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Reverse Proxy and Load Balancing: Do we need both?</title>
      <dc:creator>jiisanda🙆‍♂️</dc:creator>
      <pubDate>Thu, 10 Oct 2024 08:11:54 +0000</pubDate>
      <link>https://dev.to/jiisanda/reverse-proxy-and-load-balancing-do-we-need-both--45hc</link>
      <guid>https://dev.to/jiisanda/reverse-proxy-and-load-balancing-do-we-need-both--45hc</guid>
      <description>&lt;p&gt;In this guide, I’ll walk you through configuring Nginx as both a reverse proxy and a load balancer, along with handling SSL termination for secure client-server communication. This setup can be used widely to enhance performance, scalability for websites and APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Reverse Proxy and Load Balancing:
&lt;/h3&gt;

&lt;p&gt;Though both terminologies sound similar, reverse proxy acts as an intermediate between clients and servers. It forwards client requests to servers and relays the server’s responses back to the clients.&lt;/p&gt;

&lt;p&gt;While Load Balancer distributes incoming client requests across multiple backend servers, ensuring the load is spread evenly. It monitors server health to route traffic away from any server that becomes unavailable. &lt;/p&gt;

&lt;h3&gt;
  
  
  Do we need both ?
&lt;/h3&gt;

&lt;p&gt;Yes, in some cases. Most production environments benefit from using both. &lt;/p&gt;

&lt;p&gt;Load balancer helps to eliminate single point of failure, making API more &lt;strong&gt;reliable&lt;/strong&gt; by allowing the API to be deployed in multiple backend servers, this intern improves user experience by reducing number of errors responses for clients, as it routes requests to healthy servers. &lt;/p&gt;

&lt;p&gt;Load balancer also does health checks, which is when it sends separate &lt;strong&gt;health check&lt;/strong&gt; requests, in frequent intervals and determines a server is healthy based on specified type of response like 200 or OK. &lt;/p&gt;

&lt;p&gt;A reverse proxy hides the details of our backend servers from clients. It can also provide &lt;strong&gt;security&lt;/strong&gt; against DDoS attacks, blacklist certain IP addresses, and prevent overloading.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSL encryption and decryption&lt;/strong&gt; is CPU intensive, offloading these tasks to a reverse proxy reduces the load on your backend servers and improves overall performance.&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuring Nginx as a Reverse Proxy
&lt;/h4&gt;

&lt;p&gt;Nginx provides multiple protocols for proxying requests, including HTTP, FastGCI, SGCI, and uwsgi. We will be using HTTP:&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;proxy_pass&lt;/code&gt; directive allows Nginx to forward client requests to backend servers. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/app1&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://backed_server&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;In this configuration, a request to &lt;code&gt;/api/app1/hello&lt;/code&gt; will be provided into &lt;code&gt;http://backend_server/api/app1/hello&lt;/code&gt;. You can define multiple location blocks to handle different types of requests.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up Nginx for Load Balancing
&lt;/h4&gt;

&lt;p&gt;By using upstream directive load balancing can be set up. You can setup multiple servers in a backend pool and apply different algorithms to distribute client request&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend_pool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;host1.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;host2.exmaple.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;host3.exmaple.com&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;Here nginx forwards requests to any of the servers in the &lt;code&gt;backend_pool&lt;/code&gt;. By default Nginx uses a round-robin method, distributing requests evenly across servers.&lt;/p&gt;

&lt;h5&gt;
  
  
  Upstream Balancing Algorithms
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Round Robin (default) as above&lt;/li&gt;
&lt;li&gt;Least Connections: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sends request to server with the fewest active connections, which is useful when servers are slower than others.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend_pool&lt;/span&gt; &lt;span class="p"&gt;{&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="s"&gt;host1.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;host2.example.com&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;ul&gt;
&lt;li&gt;IP Hash&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ensures requests from the same client IP always go to the same server unless not available, important for session persistence. Here either the first three octets of IPv4 address or whole IPv6 address is used to calculate the hash value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend_pool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;ip_hash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;host1.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;host2.example.com&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;ul&gt;
&lt;li&gt;Generic Hash&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To which server to send a request to is determined from a user-defined key, which can be text, string, variable or combination. Example, a key can be paired, source IP address and port or a URI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend_pool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;hash&lt;/span&gt; &lt;span class="nv"&gt;$request_uri&lt;/span&gt; &lt;span class="s"&gt;consistent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;host1.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;host2.example.com&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;h4&gt;
  
  
  SSL Termination
&lt;/h4&gt;

&lt;p&gt;To setup HTTPS in a config file or Nginx, to allow SSL encryption and decryption reducing the load on our backend servers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;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;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/ssl/server.crt&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/server.key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_protocols&lt;/span&gt;       &lt;span class="s"&gt;TLSv1&lt;/span&gt; &lt;span class="s"&gt;TLSv1.1&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt; &lt;span class="s"&gt;TLSv1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;ssl_ciphers&lt;/span&gt;         &lt;span class="s"&gt;HIGH:!aNULL:!MD5&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;/api/hello&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_pool&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 listens on port 443 for HTTPS traffic, handles SSL encryption/decryption, and provides requests to &lt;code&gt;backend_pool&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While Nginx does not provide support for advanced health check, it allows basic health probing using &lt;code&gt;max_fails&lt;/code&gt; and &lt;code&gt;fail_timeout&lt;/code&gt; parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend_pool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;host1.example.com&lt;/span&gt; &lt;span class="s"&gt;max_fails=2&lt;/span&gt; &lt;span class="s"&gt;fail_timeout=5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;host2.example.com&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;In this configuration, if host1 fails twice within a 5-second window, Nginx will stop routing requests to it until it recovers.&lt;/p&gt;

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

&lt;p&gt;Now, we understand the load balancing and load balancing support in Nginx. To configure both, we can create a &lt;code&gt;nginx.conf&lt;/code&gt; file in the &lt;code&gt;/etc/nginx directory&lt;/code&gt;, and add the configurations as below.&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%2F0htzapvasih7l7px5mg6.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%2F0htzapvasih7l7px5mg6.png" alt="NGINX as Load Balancing and Reverse Proxy" width="800" height="446"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;events&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 for load balancing&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;host1.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;,&lt;/span&gt;
        &lt;span class="s"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;host2.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;max_fails=2&lt;/span&gt; &lt;span class="s"&gt;fail_timeout=5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_session_cache&lt;/span&gt; &lt;span class="s"&gt;shared:SSL:10m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_session_timeout&lt;/span&gt; &lt;span class="s"&gt;10ms&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;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;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;keepalive_timeout&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt;         &lt;span class="n"&gt;/etc/nginx/ssl/server.crt&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/server.key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;ssl_protocols&lt;/span&gt;           &lt;span class="s"&gt;TLSv1&lt;/span&gt; &lt;span class="s"&gt;TLSv1.1&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt; &lt;span class="s"&gt;TLSv1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;ssl_ciphers&lt;/span&gt;         &lt;span class="s"&gt;HIGH:!aNULL:!MD5&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;/service/api1&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="p"&gt;}&lt;/span&gt;

        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/service/api2&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="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;



</description>
      <category>nginx</category>
      <category>reverseproxy</category>
      <category>loadbalancing</category>
      <category>distributed</category>
    </item>
    <item>
      <title>UUID or ULID: Awesomeness of Unique Identifiers!</title>
      <dc:creator>jiisanda🙆‍♂️</dc:creator>
      <pubDate>Tue, 19 Mar 2024 15:51:13 +0000</pubDate>
      <link>https://dev.to/jiisanda/uuid-or-ulid-awesomeness-of-unique-identifiers-48cd</link>
      <guid>https://dev.to/jiisanda/uuid-or-ulid-awesomeness-of-unique-identifiers-48cd</guid>
      <description>&lt;p&gt;Welcome! In this article we are going to have the showdown of two prominent choices of unique identifiers: UUID and ULID! 😲&lt;/p&gt;

&lt;p&gt;In the landscape of software development, the task of generating unique identifiers has always been a crucial challenge. Whether it's managing database keys, tracking events in distributed systems, or ensuring session security, the choice of identifier can significantly impact the efficiency and performance of your application. In this showdown both parties present their strengths, factors that could make you choose one over the other, a glimpse of there implementation, and weaknesses. So sit back, get some popcorns 🍿, and get ready for a showdown that will empower you to make an informed decision for your next project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage Setup
&lt;/h2&gt;

&lt;p&gt;In software development, unique identifiers play a crucial role in ensuring data integrity, system scalability, and security. They act as unique markers for various entities within a system, like database records, distributed events, and user sessions. &lt;/p&gt;

&lt;p&gt;Traditional auto-incrementing IDs, while simple, can become problematic at scale, leading to performance issues, collision risks, and data leakage. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;if need explanation for any of the problems do comment happy to answer...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, the two powerful alternatives in the world of unique identifiers: UUIDs and ULIDs!&lt;/p&gt;

&lt;p&gt;UUIDs are the OGs of uniqueness, with the standardized format and 128-bit punch, these chads says, "I'm globally unique, baby!" 😎. As they boast their universal uniqueness across the cosmos💫!&lt;/p&gt;

&lt;p&gt;But then comes ULIDs, the new kids who brings the whole new steps in the game! UILDs ain't just uniqueness, but also lexicographically sorted, baby! With the blend of timestamp sweetness and randomness, ULIDs slide into your codebase like smooth saxophone 🎷 on a summer night.&lt;/p&gt;

&lt;p&gt;So what's the fuss, you ask? Well, UUIDs bring the tried-and-true reliability, perfect for when you need global uniqueness. But ULIDs? They are all about time based sorting, making them the go to identifiers where chronological order is the thing. &lt;/p&gt;

&lt;h2&gt;
  
  
  UUIDs (Universally Unique Identifiers)
&lt;/h2&gt;

&lt;p&gt;UUIDs are different from sequential ids. &lt;a href="https://datatracker.ietf.org/doc/html/rfc4122" rel="noopener noreferrer"&gt;RFC_4122&lt;/a&gt; says,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;UUIDs are of a fixed size (128 bits) which is reasonably small compared to other alternatives.  This lends itself well to sorting, ordering, and hashing of all sorts, storing in databases, simple allocation, and ease of programming in general.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Layout and Byte order of UUID
&lt;/h3&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%2F3ot2r1crsiwcz21xnb75.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%2F3ot2r1crsiwcz21xnb75.png" alt="UUID Layout - 128bit" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  timestamp
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;60 bit value&lt;/li&gt;
&lt;li&gt;UUID1: represented by UTC (Since, 00:00:00.00 15th Oct 1582)&lt;/li&gt;
&lt;li&gt;UUID3 and 5: timestamp (50 bits) is constructed from name (See Algo below)&lt;/li&gt;
&lt;li&gt;UUID4: timestamp is randomly or pseudo-randomly generated. (see algo)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  clock-sequence (14 bit)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;UUID1: clock sequence is used to help avoid duplicates that arises when clock is set backwards in time (or) if the node ID changes.&lt;/li&gt;
&lt;li&gt;UUID 3 and 5: 14-bit value constructed from a name (see Algo below)&lt;/li&gt;
&lt;li&gt;UUID4: randomly or pseudo-randomly generated. (see algo)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  node (48-bit)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;UUID1: node field is an IEEE MAC address, usually host address.&lt;/li&gt;
&lt;li&gt;UUID 3 and 5: Constructed from name (see algo)&lt;/li&gt;
&lt;li&gt;UUID4: randomly or pseudo-randomly generated (see algo)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc4122#section-4.2.1" rel="noopener noreferrer"&gt;RFC_4122: Basic Algorithm&lt;/a&gt; sates an algorithm for generating UUIDs if they do not need to be generated frequently, but there were some issues. And hence different versions of UUIDs was implemented.&lt;/p&gt;

&lt;p&gt;Let's look briefly at each and peek at it's Python &lt;a href="https://github.com/python/cpython/blob/main/Lib/uuid.py" rel="noopener noreferrer"&gt;implementation&lt;/a&gt;...&lt;/p&gt;

&lt;h3&gt;
  
  
  UUID1 (MAC Address + timestamp)
&lt;/h3&gt;

&lt;p&gt;UUID1 concatenates the 48-bit MAC Address of the "node" (computer generating the UUID), with a 60-bit timestamp. The Python implementation is as follows:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;uuid1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clock_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&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;UUID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generate a UUID from a host ID, sequence number, and the current time.
    If &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;node&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; is not given, getnode() is used to obtain the hardware
    address.  If &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;clock_seq&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; is given, it is used as the sequence number;
    otherwise a random 14-bit sequence number is chosen.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# some code
&lt;/span&gt;
    &lt;span class="n"&gt;time_low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xffffffff&lt;/span&gt;
    &lt;span class="n"&gt;time_mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xffff&lt;/span&gt;
    &lt;span class="n"&gt;time_hi_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xfff&lt;/span&gt;
    &lt;span class="n"&gt;clock_seq_low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clock_seq&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff&lt;/span&gt;
    &lt;span class="n"&gt;clock_seq_hi_variant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clock_seq&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x3f&lt;/span&gt;

    &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time_low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_mid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_hi_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;clock_seq_hi_variant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clock_seq_low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  UUID 3 and 5
&lt;/h3&gt;

&lt;p&gt;The version 3 and 5 are name-based UUIDs. For example, some name spaces are domain name system, URLs, or reserved words in programming languages. Some potential python specific name space ids are as follows:&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="n"&gt;NAMESPACE_DNS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;6ba7b810-9dad-11d1-80b4-00c04fd430c8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;NAMESPACE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;6ba7b811-9dad-11d1-80b4-00c04fd430c8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;NAMESPACE_OID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;6ba7b812-9dad-11d1-80b4-00c04fd430c8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;NAMESPACE_X500&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;6ba7b814-9dad-11d1-80b4-00c04fd430c8&lt;/span&gt;&lt;span class="sh"&gt;'&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 python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;uuid3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;namespace&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generate a UUID from the MD5 hash of a namespace UUID and a name.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# some code    
&lt;/span&gt;
    &lt;span class="n"&gt;digest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;bytes&lt;/span&gt; &lt;span class="o"&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;usedforsecurity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&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;def&lt;/span&gt; &lt;span class="nf"&gt;uuid5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;namespace&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generate a UUID from the SHA-1 hash of a namespace UUID and a name.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# some code
&lt;/span&gt;
    &lt;span class="nb"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;version&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  UUID4
&lt;/h3&gt;

&lt;p&gt;The version 4 is meant for generating UUIDs from truly-random or pseudo-random numbers&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generate a random UUID.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;version&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if none of bytes, fields is given then &lt;code&gt;class UUID()&lt;/code&gt; will generate a &lt;code&gt;TypeError&lt;/code&gt; saying &lt;code&gt;one of the hex, bytes, fields, or int argument must be given&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This was all about UUIDs, if want to know more about UUID do look at &lt;a href="https://datatracker.ietf.org/doc/html/rfc4122" rel="noopener noreferrer"&gt;RFC 4122&lt;/a&gt;...&lt;/p&gt;

&lt;h2&gt;
  
  
  ULIDs (Universally Unique Lexicographically Sortable Identifiers)
&lt;/h2&gt;

&lt;p&gt;A ULID is 128 bit compatible with UUIDs, we can be generate 1.21e+24 unique ULIDs per second. These are as the name suggest lexicographically sortable. ULIDs are case sensitive, and no special character so URL safe.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layout
&lt;/h3&gt;

&lt;p&gt;In general the structure of a ULID is as follow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 01AN4Z07BY      79KA1307SR9X4MV3

|----------|    |----------------|
 Timestamp          Randomness
   48bits             80bits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  timestamp
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;48 bit integer&lt;/li&gt;
&lt;li&gt;UNIX-time in milliseconds&lt;/li&gt;
&lt;li&gt;Won't run out of space 'til the year 10889 AD.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  randomness
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;80 bits&lt;/li&gt;
&lt;li&gt;Cryptographically secure source of randomness, if possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sorting and Encoding and Montonocity
&lt;/h3&gt;

&lt;p&gt;The left-most character must be sorted first, and the right-most character sorted last (lexical order). The default ASCII character set is used. For encoding Crockford's Base32 is used as shown below. This alphabet excludes I, L, O and U to avoid confusion and abuse.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;While generating a UUID within same millisecond, it can provide some guarantees regarding some order. So if same millisecond is detected, the &lt;code&gt;random&lt;/code&gt; component is incremented by 1 bit in the least significant bit position.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;p&gt;You usually would create a new :class:&lt;code&gt;ULID&lt;/code&gt; object by calling the default constructor with no argument. In that case it will fill the timestamp part with the current datetime. And to encode the object it is usually converted to string.&lt;/p&gt;

&lt;p&gt;You can create ULIDs, using different property passing as arguments. It can be generated using timestamp, or from uuid, from hex or byte, from string, or from datetime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of ULID over UUIDs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;shorter string representation (26 characters in ULIDs vs 36 in UUIDs)&lt;/li&gt;
&lt;li&gt;Sortability for efficient ordering and retrieval.&lt;/li&gt;
&lt;li&gt;Potential performance benefits in certain scenarios like 

&lt;ul&gt;
&lt;li&gt;In databases that uses the sorted indexes, ULIDs can potentially improve query performance because they leverage the existing sorting order of the index.&lt;/li&gt;
&lt;li&gt;When working with time-series data, ULIDs (which often includes a timestamp component) can be stored and retrieved in chronological order without additional sorting.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Choosing the Right Champion
&lt;/h2&gt;

&lt;p&gt;Now that we've explored both UUIDs and ULIDs, let's help you pick the champion for your next project!&lt;/p&gt;

&lt;p&gt;Here's is a quick comparison:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;UUIDs&lt;/th&gt;
&lt;th&gt;ULIDs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Uniqueness&lt;/td&gt;
&lt;td&gt;Guaranteed&lt;/td&gt;
&lt;td&gt;Guaranteed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sortability&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (Lexicographically)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;String Length&lt;/td&gt;
&lt;td&gt;36 character&lt;/td&gt;
&lt;td&gt;26 character&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Generally Good&lt;/td&gt;
&lt;td&gt;Potentially better with sorted indexes/time-series data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  When to choose ULIDs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sortability is essential: ULIDs excel when you need to efficiently sort or filter your identifiers.&lt;/li&gt;
&lt;li&gt;Performance optimization matters: In scenarios with sorted indexes or time-series data, ULIDs can potentially offer performance benefits.&lt;/li&gt;
&lt;li&gt;Compactness is desired: The shorter string length of ULIDs can be a space-saving advantage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When to use UUIDs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Focus on guaranteed uniqueness: If the absolute certainty of no collision is paramount, UUIDs are the established choice.&lt;/li&gt;
&lt;li&gt;Sorting isn't a priority: If order doesn't matter for your identifiers, UUIDs function perfectly well.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ultimately, the best choice depends on your specific project requirements. Weigh the importance of uniqueness, sortability, performance, and string length to make an informed decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Let's a look over how can you generate UUID and ULID in python...&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="c1"&gt;# Generate a ULID
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ulid&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ULID&lt;/span&gt;

&lt;span class="n"&gt;ulid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ULID&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&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;ULID: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ulid&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="c1"&gt;# Example output: 01HQCK8PK2T23Q13VVS03K47F9E
&lt;/span&gt;
&lt;span class="c1"&gt;# Generate a UUID (version 4 - random)
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;

&lt;span class="n"&gt;uuid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&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;UUID: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;uuid&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="c1"&gt;# Example output: 123e4567-e89b-12d3-a456-426614174000
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article has explored the strength and weaknesses of two potential contenders in the unique identifier arena: UUIDs and ULIDs.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Both UUIDs and ULIDs guarantee uniqueness, a crucial aspect for data integrity and security.&lt;/li&gt;
&lt;li&gt;UUIDs reigns supreme when prioritizing absolute uniqueness and don't require sorting capabilities. &lt;/li&gt;
&lt;li&gt;ULIDs shine when sortability and potentially improved performance  are key consideration, thanks to their lexicographically sorting and timestamp component. &lt;/li&gt;
&lt;li&gt;Their compact string representation (26 characters) offers a space-saving advantage compared to UUIDs (36 characters) &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>uniqueidentifiers</category>
      <category>uuid</category>
      <category>ulid</category>
      <category>database</category>
    </item>
    <item>
      <title>Sidecar Pattern</title>
      <dc:creator>jiisanda🙆‍♂️</dc:creator>
      <pubDate>Sat, 28 Oct 2023 21:08:55 +0000</pubDate>
      <link>https://dev.to/jiisanda/sidecar-pattern-4cp3</link>
      <guid>https://dev.to/jiisanda/sidecar-pattern-4cp3</guid>
      <description>&lt;h2&gt;
  
  
  👋 Introduction
&lt;/h2&gt;

&lt;p&gt;Have you ever played the game CS? 🎮 In CS, there are two teams: Terrorists and Counter-Terrorists, right? Let’s talk about the Terrorists team. In this team, there's a player with the bomb, while the rest of the players support the player with the bomb to plant them. It's like a well-coordinated mission where the main player has their trusted companion who assists them in planting it. 💣💥&lt;/p&gt;

&lt;p&gt;Or perhaps you've heard about sidekicks? Yeah! Like the sidekicks of superheroes. 🦸‍♂️ Just as a superhero has their trusted companion who assists them in various tasks and enhances their capabilities, a sidecar is a helper container that runs alongside a main application container in a software environment. It provides additional services, resources, or functionality to the main application, much like a sidekick complements the abilities of a superhero, making it more effective in their mission. 🦸‍♀️🚀&lt;/p&gt;

&lt;p&gt;The sidecar pattern is similar to teamwork in action! 🤝 It's a single-node pattern composed of two containers. 🚢 The first container is the application container 📦 – without it, the application wouldn't exist. Alongside the application container, there's a trusty sidecar container 🛠️. The role of the sidecar is to enhance and empower the application container, just like a sidekick bolsters a superhero! 🦸‍♂️💥&lt;/p&gt;

&lt;p&gt;These application and sidecar containers work in harmony, scheduled on the same machine, which is referred to as a 'pod.' 🌟 They share a multitude of resources, a hostname, and a network. The general sidecar pattern can be depicted as follows:&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%2F0hr0qg8z3asz7p1k5uar.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%2F0hr0qg8z3asz7p1k5uar.png" alt="general-sidecar" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📂🚗🏢 An Example Sidecar - Microservices
&lt;/h2&gt;

&lt;p&gt;In many software applications and services, various peripheral functionalities such as monitoring, logging, configuration management, and networking services are required. These functionalities can be implemented as separate components or services. &lt;br&gt;
Historically, developers would often integrate these services directly into the main application codebase, especially if they were written in the same programming language. This approach allowed for efficient code sharing and resource utilization, as these components could run in the same process as the main application. However, this tight integration also meant that these components were not well isolated, and any issues or outages in one component could potentially impact other components or even the entire application. Consequently, there was a high level of interdependence between these components and the core application.&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%2Fssrz08n6ew61v1x2jnc2.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%2Fssrz08n6ew61v1x2jnc2.png" alt="application" width="693" height="686"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem arises when these applications are built using different languages. For instance, Application 1 is built with Python, while the 2nd application is built using Rust. Each application will have its own implementations of caching, authentication, and logging.&lt;/p&gt;

&lt;p&gt;One potential solution to this problem is to develop separate API services for these functionalities, as illustrated in the figure.&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%2Fflx1amijwjn63b9ze1eg.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%2Fflx1amijwjn63b9ze1eg.png" alt="potential-solution" width="693" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Does it have any problem? &lt;br&gt;
When the application is decomposed into microservices, it becomes possible to employ different programming languages and technologies for individual services. While this approach provides greater flexibility, it comes with the drawback of each component having its own set of dependencies and the need for language-specific libraries to interact with the underlying platform and shared resources of the parent application. Furthermore, deploying these components as separate services can introduce latency into the application. The management of code and dependencies for these language-specific interfaces can also introduce significant complexity, particularly concerning aspects like hosting, deployment, and overall system management.&lt;/p&gt;

&lt;h3&gt;
  
  
  💡 Solution
&lt;/h3&gt;

&lt;p&gt;We will use a sidecar pattern.&lt;/p&gt;

&lt;p&gt;A sidecar service is not necessarily part of the application, but it is connected to it. It goes where the parent application goes. These are supporting processes or services that are deployed with the primary application. For each instance of the application, an instance of the sidecar is deployed and hosted alongside it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdwu1h6wqyiy73pi1vkob.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%2Fdwu1h6wqyiy73pi1vkob.png" alt="sidecar" width="635" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  🌟 Advantages of using a sidecar pattern:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;The sidecar can access the same resources as the primary application. It can effectively monitor system resources utilized by both itself and parent applications. Resource Access.&lt;/li&gt;
&lt;li&gt;The sidecar pattern is commonly employed with the containers and is often referred to as a sidecar container.&lt;/li&gt;
&lt;li&gt;A sidecar can be used to enhance functionality by attaching it as a separate process in the same host.&lt;/li&gt;
&lt;li&gt;A sidecar operates autonomously from the primary application, both in terms of the runtime environment and programming language, which eliminates the need to develop separate sidecar for each language.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  🕐🤔 When can this pattern can be used:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;When building a PaaS with Sidecars&lt;/li&gt;
&lt;/ol&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%2F3c228u75jyaow70xkle3.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%2F3c228u75jyaow70xkle3.png" alt="PaaS with sidecar" width="761" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Managing a dynamic configuration&lt;/li&gt;
&lt;li&gt;When a component or feature must be co-located on the same host as the application.&lt;/li&gt;
&lt;li&gt;A service that shares the overall lifecycle of your main application, but can be independently updated.&lt;/li&gt;
&lt;li&gt;A component is owned by a different organization.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  🚫❌ But not suitable when:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Communication between a parent application and sidecar services includes some overhead. i.e., where inter-process communication is important.&lt;/li&gt;
&lt;li&gt;For small applications, the cost of deploying a sidecar service for each instance is not worth the isolation.&lt;/li&gt;
&lt;li&gt;When the service needs to scale differently from the main applications. If so, it's better to deploy the feature as a separate service. &lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  🔗 Further Reading and References
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/architecture/patterns/sidecar" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/azure/architecture/patterns/sidecar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/designing-distributed-systems/9781491983638/ch02.html" rel="noopener noreferrer"&gt;https://www.oreilly.com/library/view/designing-distributed-systems/9781491983638/ch02.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>sidecarpattern</category>
      <category>microservices</category>
    </item>
    <item>
      <title>How does python-dotenv simplify Configuration Management?</title>
      <dc:creator>jiisanda🙆‍♂️</dc:creator>
      <pubDate>Fri, 21 Jul 2023 14:08:50 +0000</pubDate>
      <link>https://dev.to/jiisanda/how-does-python-dotenv-simplify-configuration-management-3ne6</link>
      <guid>https://dev.to/jiisanda/how-does-python-dotenv-simplify-configuration-management-3ne6</guid>
      <description>&lt;p&gt;Navigating through the python projects, we can quickly realize that handling configurations can be like exploring mazes with numerous paths to choose from. In this article, we’ll embark on a thrilling journey and delve into the world of environment variables in Python, with particular focus on the realm of &lt;code&gt;.env&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;First, let’s understand what configuration management is. I just finished a Netflix series, related to space travel, so picture this. You are a captain of your spaceship, commanding a crew of space travelers. Your spaceship is equipped with a range of cool gadgets and futuristic technologies, each with its own set of settings and values. The settings might include the ship’s speed, destination coordinates, communication frequencies, and more.&lt;/p&gt;

&lt;p&gt;Now as you venture through the vastness of the cosmos, you encounter different planets, each with its unique challenges and environments. On some planets, you need to fly at a slower speed to avoid debris, while on others you might need to crank up the communication frequencies to establish contact with alien civilization. &lt;/p&gt;

&lt;p&gt;In spaceship jargon, these settings are called configuration variables. And here’s where &lt;code&gt;python-dotenv&lt;/code&gt; comes into play - it’s like having a magical map that stores all the settings separately, making your life as captain so much easier!&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;python-dotenv&lt;/code&gt;, you can create a special treasure chest called &lt;code&gt;.env&lt;/code&gt;, where you write down all the configuration variables for each planet. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SPEED=10
DESTINATION_X=234
DESTINATION_Y=567
COMMUNICATION_FREQ=200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, whenever you approach a new planet, you consult your treasure chest and quickly update your spaceship’s settings without tinkering with the spaceship’s control panel directly. It’s like casting the spell to magically adjust the ship’s speed and communication frequencies for each destination!&lt;/p&gt;

&lt;p&gt;The best part? Since the &lt;code&gt;.env&lt;/code&gt; treasure chest is hidden safely in your spaceship’s storage room, you can keep all your top-secret settings secure from prying eyes - even from other spaceship crew who might be curious about your awesome adventures.&lt;/p&gt;

&lt;p&gt;So with &lt;code&gt;python-dotenv&lt;/code&gt;, you become the master of configuration management, effortlessly adapting to different planets and situations, all while keeping your spaceship’s secret safe and sound. 🙆‍♂️🚀✨ &lt;/p&gt;

&lt;p&gt;Okay Enough! Let’s jump into some technical stuff, understanding how to use python-dotenv and behind the scenes… &lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 What is python-dotenv?
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://pypi.org/project/python-dotenv/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;, python-dotenv defines itself as &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Python-dotenv reads key-value pairs from a .env file and can set them as environment variables. It helps in the development of applications following the 12-factor principles.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s understand this first, &lt;code&gt;key-value&lt;/code&gt; pairs are a way of organizing data, where each piece of data is associated with a unique key. &lt;code&gt;12-factor principles&lt;/code&gt;, are a set of best practices for building modern scalable, maintainable software applications. One of these principles involves storing configuration in the environment, which means using environment variables to manage configuration instead of hardcoding them into the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  🏃‍♂️💨 Getting Started with python-dotenv
&lt;/h3&gt;

&lt;p&gt;Install python-dotenv using&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install python-dotenv&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Make sure you activate your virtual environment, if not activated.&lt;br&gt;
This will add python-dotenv to your application, to make it load the configuration from the &lt;code&gt;.env&lt;/code&gt; file when it is present (eg., in development).&lt;/p&gt;

&lt;p&gt;To configure the development environment, add a &lt;code&gt;.env&lt;/code&gt; in the root directory of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── .env
└── main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax for writing in the '.env' file for python-dotenv is similar to Bash.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Spaceship Config
DOMAIN=dev.to
CAPTAIN_EMAIL=captain@${DOMAIN}
DESINATION_PLANET=${DOMAIN}/priplanus
SPEED=10
DESTINATION_X=234
DESTINATION_Y=567
COMMUNICATION_FREQ=200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also make sure to add &lt;code&gt;.env&lt;/code&gt; file to &lt;code&gt;.gitignore&lt;/code&gt;, especially if it contains secrets like passwords.&lt;br&gt;
How to load/use these environment variables in &lt;code&gt;main.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

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

import os
from dotenv import load_dotenv

load_dotenv() # takes environment variables from .env

SPEED = os.getenv(“SPEED”) # or use os.environ(“SPEED”)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how you would be able to use environment variables in a Python Project. Easy isn’t it? Now let’s discuss what happens when you call &lt;code&gt;load_dotenv()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔌📥 load_dotenv()
&lt;/h2&gt;

&lt;p&gt;Disclaimer: Source of all the data I am to provide is from &lt;a href="https://github.com/theskumar/python-dotenv" rel="noopener noreferrer"&gt;GitHub of python-dotenv&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When you call &lt;code&gt;load_dotenv()&lt;/code&gt; from the &lt;code&gt;dotenv&lt;/code&gt; package, it can optionally accept an argument called &lt;code&gt;dotenv_path: Optional[StrPath]&lt;/code&gt; or &lt;code&gt;stream: Optional[IO[str]]&lt;/code&gt;, which allows you to specify the path to a custom &lt;code&gt;.env&lt;/code&gt; file for loading environment variables. If you don't provide the &lt;code&gt;dotenv_path&lt;/code&gt; or &lt;code&gt;stream&lt;/code&gt;, the function uses &lt;code&gt;find_dotenv()&lt;/code&gt; to search for the &lt;code&gt;.env&lt;/code&gt; file in increasingly higher folders within the project. Once it finds the file, it loads the environment variables from it.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;find_dotenv()&lt;/code&gt; function returns the path to the &lt;code&gt;.env&lt;/code&gt; file if it is found, or an empty string if it doesn't find the file.&lt;/p&gt;

&lt;p&gt;Now, we have the file path, so &lt;code&gt;load_dotenv()&lt;/code&gt; calls the class &lt;code&gt;DotEnv&lt;/code&gt;, which does the main part of loading all the variables found as environment variables.&lt;/p&gt;

&lt;p&gt;So, &lt;code&gt;DotEnv&lt;/code&gt; has a method called &lt;code&gt;set_as_environment_variables&lt;/code&gt;, which loads the current dotenv as a system variable. Here is how it is implemented.&lt;/p&gt;

&lt;p&gt;Once &lt;code&gt;find_dotenv(&lt;/code&gt;) locates the .env file, &lt;code&gt;load_dotenv()&lt;/code&gt; proceeds to call the &lt;code&gt;DotEnv&lt;/code&gt; class to perform the crucial task of loading all the variables found in the &lt;code&gt;.env&lt;/code&gt; file as environment variables.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;DotEnv&lt;/code&gt; class contains a method named &lt;code&gt;set_as_environment_variables&lt;/code&gt;, which handles the process of setting the values from the &lt;code&gt;.env&lt;/code&gt; file as system-level environment variables. This means that after invoking this method, the variables defined in the &lt;code&gt;.env&lt;/code&gt; file become accessible as environment variables throughout the entire Python application.&lt;/p&gt;

&lt;p&gt;Here is how it is implemented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;01 def set_as_environment_variables(self) -&amp;gt; bool:
02         if not self.dict():
03             return False
04 
05         for k, v in self.dict().items():
06             if k in os.environ and not self.override:
07                 continue
08             if v is not None:
09                 os.environ[k] = v
10 
11         return True

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;dict()&lt;/code&gt; is a method in the &lt;code&gt;DotEnv&lt;/code&gt; class, which returns dotenv as a dictionary. After checking all the conditions, in line 09 of the above listing, the environment variables are set.&lt;/p&gt;

&lt;p&gt;Here, &lt;code&gt;self.overside: bool&lt;/code&gt;, is by default set to &lt;code&gt;True&lt;/code&gt;. If in &lt;code&gt;load_dotenv&lt;/code&gt;, you add an argument as &lt;code&gt;load_dotenv(override=False)&lt;/code&gt;, then, the already present environment variable will not be updated.&lt;/p&gt;

&lt;p&gt;And this is how python-dotenv works, behind the scenes, for setting the environment variables. There are more features of python-dotenv like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load configuration without altering the environment&lt;/li&gt;
&lt;li&gt;Parse configuration as a stream&lt;/li&gt;
&lt;li&gt;Load .env files in IPython&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Go through the &lt;a href="https://pypi.org/project/python-dotenv/" rel="noopener noreferrer"&gt;docs&lt;/a&gt; and the &lt;a href="https://github.com/theskumar/python-dotenv" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, to see how these features work. &lt;/p&gt;




&lt;h2&gt;
  
  
  ⌚👋👋 Outro
&lt;/h2&gt;

&lt;p&gt;And now, armed with the power of &lt;code&gt;python-dotenv&lt;/code&gt;, you, the spaceship captain, navigated the cosmos with ease, effortlessly adjusting to the unique challenges of each planet. &lt;/p&gt;

&lt;p&gt;Happy coding, see you soon in the next article. 🚀✨🌌&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://github.com/jiisanda" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/jiisanda/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and Subscribe my &lt;a href="https://www.youtube.com/@codeakey" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>python</category>
      <category>environmentvariables</category>
      <category>dotenv</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
