<?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: Kshitij Sharma</title>
    <description>The latest articles on DEV Community by Kshitij Sharma (@kshitij_sharma_fd33fdb032).</description>
    <link>https://dev.to/kshitij_sharma_fd33fdb032</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3892871%2Fb33f228c-f438-4022-9db2-6b287297b3c4.png</url>
      <title>DEV Community: Kshitij Sharma</title>
      <link>https://dev.to/kshitij_sharma_fd33fdb032</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kshitij_sharma_fd33fdb032"/>
    <language>en</language>
    <item>
      <title>TerraWeek Challenge – Day 5 : Terraform Modules: Writing Reusable Infrastructure</title>
      <dc:creator>Kshitij Sharma</dc:creator>
      <pubDate>Thu, 16 Jul 2026 10:26:44 +0000</pubDate>
      <link>https://dev.to/kshitij_sharma_fd33fdb032/terraweek-challenge-day-5-terraform-modules-writing-reusable-infrastructure-2le6</link>
      <guid>https://dev.to/kshitij_sharma_fd33fdb032/terraweek-challenge-day-5-terraform-modules-writing-reusable-infrastructure-2le6</guid>
      <description>&lt;p&gt;📅 &lt;strong&gt;Date:&lt;/strong&gt; 16 July 2026&lt;/p&gt;

&lt;p&gt;Welcome to &lt;strong&gt;Day 5&lt;/strong&gt; of my &lt;strong&gt;TerraWeek Challenge!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;p&gt;During the previous four days, I learned how to write Terraform configurations, provision AWS infrastructure, manage Terraform State, and configure Remote Backends.&lt;/p&gt;

&lt;p&gt;Today's challenge focused on one of Terraform's most powerful features—&lt;strong&gt;Modules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Until now, every infrastructure component was written directly inside the root configuration. While that approach works for small projects, it quickly becomes difficult to maintain as infrastructure grows.&lt;/p&gt;

&lt;p&gt;Imagine creating the same EC2 configuration multiple times for different environments.&lt;/p&gt;

&lt;p&gt;Instead of copying and pasting hundreds of lines of Terraform code, Modules allow us to package infrastructure into reusable building blocks.&lt;/p&gt;

&lt;p&gt;This makes Infrastructure as Code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cleaner&lt;/li&gt;
&lt;li&gt;Easier to maintain&lt;/li&gt;
&lt;li&gt;Reusable&lt;/li&gt;
&lt;li&gt;Consistent&lt;/li&gt;
&lt;li&gt;Easier to test&lt;/li&gt;
&lt;li&gt;Easier to version&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Today's challenge introduced me to the concepts of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Root Modules&lt;/li&gt;
&lt;li&gt;Child Modules&lt;/li&gt;
&lt;li&gt;Local Modules&lt;/li&gt;
&lt;li&gt;Registry Modules&lt;/li&gt;
&lt;li&gt;Git Modules&lt;/li&gt;
&lt;li&gt;Module Version Pinning&lt;/li&gt;
&lt;li&gt;Module Composition&lt;/li&gt;
&lt;li&gt;Reusing Modules with &lt;code&gt;for_each&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end of today's challenge, I understood why almost every production Terraform project is built around reusable modules rather than large monolithic Terraform files.&lt;/p&gt;




&lt;h1&gt;
  
  
  📚 Learning Objectives
&lt;/h1&gt;

&lt;p&gt;By the end of Day 5, I was able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand what Terraform Modules are.&lt;/li&gt;
&lt;li&gt;Learn why Modules improve Infrastructure as Code.&lt;/li&gt;
&lt;li&gt;Understand the difference between Root Modules and Child Modules.&lt;/li&gt;
&lt;li&gt;Create my own reusable Local Module.&lt;/li&gt;
&lt;li&gt;Pass values into Modules using Variables.&lt;/li&gt;
&lt;li&gt;Read values from Modules using Outputs.&lt;/li&gt;
&lt;li&gt;Understand why Modules should receive IDs as inputs.&lt;/li&gt;
&lt;li&gt;Consume Modules from the Terraform Registry.&lt;/li&gt;
&lt;li&gt;Understand Git-based Modules.&lt;/li&gt;
&lt;li&gt;Learn different ways to pin Module versions.&lt;/li&gt;
&lt;li&gt;Instantiate multiple Modules using &lt;code&gt;for_each&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Explore Module Composition.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🤔 What is a Terraform Module?
&lt;/h1&gt;

&lt;p&gt;A &lt;strong&gt;Terraform Module&lt;/strong&gt; is simply a collection of Terraform configuration files grouped together to perform a specific task.&lt;/p&gt;

&lt;p&gt;Instead of writing the same infrastructure repeatedly, we can package it into a reusable module and call it whenever needed.&lt;/p&gt;

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

&lt;p&gt;Instead of writing an EC2 Instance configuration three different times:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Development&lt;/li&gt;
&lt;li&gt;Staging&lt;/li&gt;
&lt;li&gt;Production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;we can create one reusable EC2 Module and use it across all environments.&lt;/p&gt;

&lt;p&gt;Think of a Module as a reusable function in programming.&lt;/p&gt;

&lt;p&gt;You write it once...&lt;/p&gt;

&lt;p&gt;...and use it as many times as you want.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏗️ Why Do We Need Modules?
&lt;/h1&gt;

&lt;p&gt;As Terraform projects grow, the amount of Infrastructure as Code also grows.&lt;/p&gt;

&lt;p&gt;Without Modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code duplication increases.&lt;/li&gt;
&lt;li&gt;Maintenance becomes difficult.&lt;/li&gt;
&lt;li&gt;Bugs need to be fixed in multiple places.&lt;/li&gt;
&lt;li&gt;Infrastructure becomes inconsistent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modules solve these problems by keeping infrastructure reusable and standardized.&lt;/p&gt;

&lt;p&gt;Instead of updating ten different EC2 configurations, we update one Module.&lt;/p&gt;

&lt;p&gt;Every environment automatically benefits from the change.&lt;/p&gt;

&lt;p&gt;This significantly reduces maintenance effort.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌍 Root Module vs Child Module
&lt;/h1&gt;

&lt;p&gt;One of the most important concepts I learned today was the difference between the &lt;strong&gt;Root Module&lt;/strong&gt; and a &lt;strong&gt;Child Module&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Root Module
&lt;/h2&gt;

&lt;p&gt;The Root Module is the Terraform project that we execute directly.&lt;/p&gt;

&lt;p&gt;This is where we run commands like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init

terraform plan

terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Root Module usually contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provider Configuration&lt;/li&gt;
&lt;li&gt;Data Sources&lt;/li&gt;
&lt;li&gt;Variables&lt;/li&gt;
&lt;li&gt;Module Calls&lt;/li&gt;
&lt;li&gt;Outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It acts as the entry point for the entire Terraform project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Child Module
&lt;/h2&gt;

&lt;p&gt;A Child Module is a reusable Terraform package that is called by another module.&lt;/p&gt;

&lt;p&gt;Instead of creating infrastructure directly, it receives inputs from the Root Module and returns useful outputs.&lt;/p&gt;

&lt;p&gt;In today's project, the reusable EC2 module is the Child Module.&lt;/p&gt;

&lt;p&gt;This design keeps the infrastructure modular and much easier to maintain.&lt;/p&gt;




&lt;h1&gt;
  
  
  ✨ Benefits of Using Modules
&lt;/h1&gt;

&lt;p&gt;Modules provide several important advantages.&lt;/p&gt;

&lt;p&gt;Some of the biggest benefits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reusability&lt;/li&gt;
&lt;li&gt;Consistency&lt;/li&gt;
&lt;li&gt;Encapsulation&lt;/li&gt;
&lt;li&gt;Versioning&lt;/li&gt;
&lt;li&gt;Easier Testing&lt;/li&gt;
&lt;li&gt;Better Team Collaboration&lt;/li&gt;
&lt;li&gt;Cleaner Project Structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of maintaining hundreds of duplicated Terraform resources, Modules allow us to centralize infrastructure logic in a single place.&lt;/p&gt;

&lt;p&gt;This is one of the main reasons why Modules are considered the backbone of scalable Terraform projects.&lt;/p&gt;




&lt;h1&gt;
  
  
  📂 Project Structure
&lt;/h1&gt;

&lt;p&gt;Today's project consists of two parts.&lt;/p&gt;

&lt;p&gt;The Root Module lives at the project root, while the reusable EC2 Module is stored inside the &lt;code&gt;modules&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Day-05/
│
├── main.tf
├── outputs.tf
├── terraform.tf
│
├── modules/
│
│   └── ec2_instance/
│       ├── main.tf
│       ├── variables.tf
│       ├── outputs.tf
│       └── README.md
│
├── README.md
└── images/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Root Module calls the Child Module whenever an EC2 instance needs to be created.&lt;/p&gt;

&lt;p&gt;This separation keeps infrastructure reusable and organized.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6qvs9eu37qgqxvtsmgnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6qvs9eu37qgqxvtsmgnz.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📁 Understanding the Module Structure
&lt;/h1&gt;

&lt;p&gt;A well-designed Terraform Module typically contains four files.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;main.tf&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Contains the infrastructure resources.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;EC2 Instance&lt;/li&gt;
&lt;li&gt;Security Groups&lt;/li&gt;
&lt;li&gt;IAM Roles&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;variables.tf&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Defines every input the Module expects.&lt;/p&gt;

&lt;p&gt;Instead of hardcoding values, the Module receives them from the Root Module.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;outputs.tf&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Exports useful information back to the Root Module.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Instance ID&lt;/li&gt;
&lt;li&gt;Public IP&lt;/li&gt;
&lt;li&gt;Private IP&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;README.md&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Explains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Module purpose&lt;/li&gt;
&lt;li&gt;Required Inputs&lt;/li&gt;
&lt;li&gt;Outputs&lt;/li&gt;
&lt;li&gt;Usage Examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Documenting Modules is considered a best practice because other developers can quickly understand how to use them.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ Prerequisites
&lt;/h1&gt;

&lt;p&gt;Before working with Terraform Modules, I ensured that the following tools were installed and configured correctly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform&lt;/li&gt;
&lt;li&gt;AWS CLI&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;li&gt;AWS Account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the module provisions AWS resources, valid AWS credentials are required before running Terraform.&lt;/p&gt;




&lt;h1&gt;
  
  
  🛠️ Verifying Terraform Installation
&lt;/h1&gt;

&lt;p&gt;The first step was verifying the installed Terraform version.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform displayed the currently installed version.&lt;/p&gt;

&lt;p&gt;This confirms that the required Terraform version is available before initializing the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbai4brogji5pk9hfperk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbai4brogji5pk9hfperk.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ☁️ Verifying AWS CLI
&lt;/h1&gt;

&lt;p&gt;Before provisioning infrastructure, I verified my AWS credentials.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws sts get-caller-identity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform uses these credentials to authenticate with AWS.&lt;/p&gt;

&lt;p&gt;A successful response confirmed that my AWS CLI was configured correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7dj0dr6q9v4yfhdvntr5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7dj0dr6q9v4yfhdvntr5.png" alt=" " width="799" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🧩 Understanding the Root Module
&lt;/h1&gt;

&lt;p&gt;In every Terraform project, there is always one &lt;strong&gt;Root Module&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The Root Module is the starting point of the entire Terraform configuration. It is responsible for initializing providers, fetching required data, calling reusable modules, and exposing useful outputs.&lt;/p&gt;

&lt;p&gt;In today's project, the Root Module contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;terraform.tf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main.tf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;outputs.tf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike previous days where the infrastructure was written directly inside &lt;code&gt;main.tf&lt;/code&gt;, today's Root Module delegates the actual EC2 creation to a reusable Child Module.&lt;/p&gt;

&lt;p&gt;Its responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configuring the AWS Provider&lt;/li&gt;
&lt;li&gt;Looking up the latest Amazon Linux AMI&lt;/li&gt;
&lt;li&gt;Resolving required IDs (Subnet, Security Group)&lt;/li&gt;
&lt;li&gt;Passing those values to the reusable module&lt;/li&gt;
&lt;li&gt;Reading outputs from the module&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation keeps the Root Module lightweight while the infrastructure logic remains encapsulated inside the Child Module.&lt;/p&gt;




&lt;h1&gt;
  
  
  📦 Understanding the Child Module
&lt;/h1&gt;

&lt;p&gt;The reusable EC2 Module is located inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;modules/
└── ec2_instance/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This module is responsible for creating a single EC2 Instance.&lt;/p&gt;

&lt;p&gt;Instead of hardcoding infrastructure values, the module accepts everything as &lt;strong&gt;inputs&lt;/strong&gt;, making it reusable across different environments, VPCs, AWS accounts, and regions.&lt;/p&gt;

&lt;p&gt;The module itself contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main.tf
variables.tf
outputs.tf
README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file has a dedicated responsibility.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;main.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates the EC2 instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;variables.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Accepts input variables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;outputs.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Exports useful values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Documents how to use the module&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is considered the standard structure for production-quality Terraform modules.&lt;/p&gt;




&lt;h1&gt;
  
  
  📥 Module Inputs
&lt;/h1&gt;

&lt;p&gt;One of the key ideas behind Terraform Modules is &lt;strong&gt;Inputs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Inputs make a module configurable.&lt;/p&gt;

&lt;p&gt;Instead of embedding values inside the module, the Root Module supplies them when calling the module.&lt;/p&gt;

&lt;p&gt;Typical inputs include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instance Name&lt;/li&gt;
&lt;li&gt;AMI ID&lt;/li&gt;
&lt;li&gt;Instance Type&lt;/li&gt;
&lt;li&gt;Subnet ID&lt;/li&gt;
&lt;li&gt;Security Group IDs&lt;/li&gt;
&lt;li&gt;Environment&lt;/li&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"web_server"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/ec2_instance"&lt;/span&gt;

  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"web"&lt;/span&gt;

  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;

  &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;

  &lt;span class="nx"&gt;ami&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_ami&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;al2023&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;subnet_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_id&lt;/span&gt;

  &lt;span class="nx"&gt;vpc_security_group_ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;security_group_ids&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This approach keeps the module flexible and reusable.&lt;/p&gt;




&lt;h1&gt;
  
  
  📤 Module Outputs
&lt;/h1&gt;

&lt;p&gt;Modules can also return useful information back to the Root Module.&lt;/p&gt;

&lt;p&gt;Instead of searching AWS manually, Terraform exposes outputs from the Child Module.&lt;/p&gt;

&lt;p&gt;Typical outputs include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instance ID&lt;/li&gt;
&lt;li&gt;Public IP&lt;/li&gt;
&lt;li&gt;Private IP&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"web_public_ip"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_ip&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Outputs make it easier for other modules, automation pipelines, or users to consume infrastructure information.&lt;/p&gt;




&lt;h1&gt;
  
  
  💡 Why Pass IDs Instead of Performing Lookups?
&lt;/h1&gt;

&lt;p&gt;One of the most interesting design decisions in today's challenge was that the Child Module does &lt;strong&gt;not&lt;/strong&gt; perform its own data lookups.&lt;/p&gt;

&lt;p&gt;Instead, the Root Module resolves everything once and passes the values into the module.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;ami&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_ami&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;al2023&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of placing the &lt;code&gt;data "aws_ami"&lt;/code&gt; block inside every module.&lt;/p&gt;

&lt;p&gt;This has several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better performance&lt;/li&gt;
&lt;li&gt;Avoids repeated API calls&lt;/li&gt;
&lt;li&gt;Keeps the module reusable&lt;/li&gt;
&lt;li&gt;Makes testing easier&lt;/li&gt;
&lt;li&gt;Keeps the module cloud-agnostic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is considered a Terraform best practice and is also the approach demonstrated in the assignment. :contentReference[oaicite:0]{index=0}&lt;/p&gt;




&lt;h1&gt;
  
  
  📍 Calling a Local Module
&lt;/h1&gt;

&lt;p&gt;Terraform allows us to reference a module stored inside the current project.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"web_server"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/ec2_instance"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;source&lt;/code&gt; attribute tells Terraform where the module is located.&lt;/p&gt;

&lt;p&gt;Since today's module is stored locally, Terraform loads it directly from the filesystem.&lt;/p&gt;

&lt;p&gt;During initialization, Terraform automatically discovers and prepares the module for use.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌎 Using Modules from the Terraform Registry
&lt;/h1&gt;

&lt;p&gt;Terraform also provides an official &lt;strong&gt;Terraform Registry&lt;/strong&gt;, which hosts thousands of reusable modules maintained by HashiCorp and the community.&lt;/p&gt;

&lt;p&gt;Instead of writing everything from scratch, we can use existing production-ready modules.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"vpc"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-aws-modules/vpc/aws"&lt;/span&gt;

  &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 5.0"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Using Registry Modules significantly reduces development time while promoting standardized infrastructure.&lt;/p&gt;

&lt;p&gt;The assignment specifically encouraged exploring Registry Modules and pinning their versions. :contentReference[oaicite:1]{index=1}&lt;/p&gt;




&lt;h1&gt;
  
  
  🔗 Using Modules from Git
&lt;/h1&gt;

&lt;p&gt;Modules can also be stored inside Git repositories.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"network"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::https://github.com/example/terraform-modules.git//network?ref=v1.0.0"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform downloads the module directly from the repository.&lt;/p&gt;

&lt;p&gt;Git Modules are commonly used when organizations maintain their own internal module library.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔒 Module Version Pinning
&lt;/h1&gt;

&lt;p&gt;One of today's biggest lessons was understanding &lt;strong&gt;Module Version Pinning&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Without version pinning, Terraform always downloads the latest available version.&lt;/p&gt;

&lt;p&gt;This can unexpectedly introduce breaking changes.&lt;/p&gt;

&lt;p&gt;To avoid this, versions should always be pinned.&lt;/p&gt;

&lt;p&gt;Some common strategies include:&lt;/p&gt;

&lt;h3&gt;
  
  
  Exact Version
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"= 5.1.2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Compatible Minor Versions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 5.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5.0.x
5.1.x
5.2.x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But blocks:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  Version Range
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 5.0, &amp;lt; 6.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful when supporting multiple compatible releases.&lt;/p&gt;




&lt;h3&gt;
  
  
  Git Tag
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::https://github.com/org/repo.git//module?ref=v1.2.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Git Commit SHA
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::https://github.com/org/repo.git//module?ref=8d0f5d8b2..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using a full commit SHA provides maximum reproducibility because the module code can never change.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Why Version Pinning Matters
&lt;/h1&gt;

&lt;p&gt;Version pinning offers several important benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reproducible deployments&lt;/li&gt;
&lt;li&gt;Stable infrastructure&lt;/li&gt;
&lt;li&gt;Protection from breaking changes&lt;/li&gt;
&lt;li&gt;Consistent CI/CD pipelines&lt;/li&gt;
&lt;li&gt;Easier debugging&lt;/li&gt;
&lt;li&gt;Predictable upgrades&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Professional Terraform projects almost always pin provider versions and module versions to ensure infrastructure behaves consistently across environments.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 Modular Composition using &lt;code&gt;for_each&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Another powerful concept introduced today was &lt;strong&gt;Module Composition&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of calling the same module repeatedly, Terraform allows us to instantiate multiple copies using &lt;code&gt;for_each&lt;/code&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"servers"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/ec2_instance"&lt;/span&gt;

  &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toset&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"worker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"cache"&lt;/span&gt;
  &lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;

  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;

  &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;

  &lt;span class="nx"&gt;ami&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_ami&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;al2023&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;subnet_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_id&lt;/span&gt;

  &lt;span class="nx"&gt;vpc_security_group_ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;security_group_ids&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;With a single module definition, Terraform can provision multiple EC2 instances while keeping the configuration concise and maintainable. This pattern is one of the main practical tasks in the Day 5 assignment. :contentReference[oaicite:2]{index=2}&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Deploying Infrastructure using Terraform Modules
&lt;/h1&gt;

&lt;p&gt;With the Root Module and Child Module ready, it was finally time to deploy infrastructure using my own reusable Terraform Module.&lt;/p&gt;

&lt;p&gt;Unlike the previous days where all infrastructure was written directly inside the root configuration, today's deployment was much cleaner.&lt;/p&gt;

&lt;p&gt;The Root Module simply passed the required inputs to the Child Module, while the Child Module handled the actual EC2 creation.&lt;/p&gt;

&lt;p&gt;This separation of responsibilities is one of the biggest reasons why Terraform Modules are considered a best practice for Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;The deployment workflow looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write Root Module

        │

        ▼

Call Child Module

        │

        ▼

terraform init

        │

        ▼

Download Module

        │

        ▼

terraform plan

        │

        ▼

terraform apply

        │

        ▼

Verify EC2 Instance

        │

        ▼

terraform output

        │

        ▼

Reuse Module using for_each
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🚀 Step 1 — Initialize Terraform
&lt;/h1&gt;

&lt;p&gt;The first step was initializing the Terraform project.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Unlike the previous days, Terraform now performed two tasks during initialization.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downloaded the AWS Provider.&lt;/li&gt;
&lt;li&gt;Initialized the Local Module.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform automatically discovered the Child Module inside:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;and prepared it for execution.&lt;/p&gt;

&lt;p&gt;Once everything completed successfully, Terraform displayed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Terraform has been successfully initialized!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirmed that both the provider and the reusable module were ready.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu7q7sj1ikmml8mlsh9bf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu7q7sj1ikmml8mlsh9bf.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📋 Step 2 — Review the Execution Plan
&lt;/h1&gt;

&lt;p&gt;Before creating any infrastructure, I reviewed the execution plan.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform evaluated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Root Module&lt;/li&gt;
&lt;li&gt;Child Module&lt;/li&gt;
&lt;li&gt;Variables&lt;/li&gt;
&lt;li&gt;Outputs&lt;/li&gt;
&lt;li&gt;Resource Dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then it displayed every resource that would be created.&lt;/p&gt;

&lt;p&gt;Since the infrastructure itself lives inside the Child Module, the execution plan clearly showed Terraform expanding the module before provisioning resources.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.web_server.aws_instance.this
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This demonstrated how Terraform internally resolves module resources.&lt;/p&gt;

&lt;p&gt;Reviewing the execution plan before deployment helps prevent accidental infrastructure changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq6vxi01b4py1xej97rzk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq6vxi01b4py1xej97rzk.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Step 3 — Provision Infrastructure
&lt;/h1&gt;

&lt;p&gt;Once I verified the execution plan, I deployed the infrastructure.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform displayed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you want to perform these actions?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After confirming with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform provisioned the infrastructure by calling the Child Module.&lt;/p&gt;

&lt;p&gt;Instead of creating resources directly from the Root Module, Terraform executed the reusable EC2 Module.&lt;/p&gt;

&lt;p&gt;After a few moments Terraform displayed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apply complete!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirmed that the EC2 instance had been successfully provisioned using my own reusable Terraform Module.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuk6tgq6r3dcfd60esmuv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuk6tgq6r3dcfd60esmuv.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ☁️ Verifying the EC2 Instance
&lt;/h1&gt;

&lt;p&gt;After Terraform completed successfully, I opened the AWS Management Console.&lt;/p&gt;

&lt;p&gt;Inside the EC2 Dashboard, I verified that the instance had been created successfully.&lt;/p&gt;

&lt;p&gt;I confirmed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instance Name&lt;/li&gt;
&lt;li&gt;Instance Type&lt;/li&gt;
&lt;li&gt;Running State&lt;/li&gt;
&lt;li&gt;Public IP Address&lt;/li&gt;
&lt;li&gt;Availability Zone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Seeing the EC2 instance created entirely through a reusable Terraform Module reinforced the practical value of modular Infrastructure as Code.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftenfedh9esj11jp0ff58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftenfedh9esj11jp0ff58.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📤 Viewing Module Outputs
&lt;/h1&gt;

&lt;p&gt;One of the biggest advantages of Terraform Modules is the ability to expose useful information through Outputs.&lt;/p&gt;

&lt;p&gt;Instead of manually locating resource details inside AWS, Terraform displays them automatically.&lt;/p&gt;

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

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;instance_id = "i-xxxxxxxxxxxxxxxx"

public_ip = "xx.xx.xx.xx"

private_ip = "172.xx.xx.xx"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These values are actually produced inside the Child Module and then returned to the Root Module.&lt;/p&gt;

&lt;p&gt;This makes modules easy to integrate with other modules and automation pipelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fecoccdkudqo25d3a0sgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fecoccdkudqo25d3a0sgc.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 Creating Multiple EC2 Instances using &lt;code&gt;for_each&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;One of today's most interesting tasks was learning that the same module can be instantiated multiple times.&lt;/p&gt;

&lt;p&gt;Instead of writing three different EC2 resources, Terraform allows us to reuse a single module.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"servers"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/ec2_instance"&lt;/span&gt;

  &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toset&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"worker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"cache"&lt;/span&gt;
  &lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;

  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;

  &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;

  &lt;span class="nx"&gt;ami&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_ami&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;al2023&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;subnet_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet_id&lt;/span&gt;

  &lt;span class="nx"&gt;vpc_security_group_ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;security_group_ids&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;When Terraform evaluates this configuration, it automatically creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App Server&lt;/li&gt;
&lt;li&gt;Worker Server&lt;/li&gt;
&lt;li&gt;Cache Server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;without duplicating the module code.&lt;/p&gt;

&lt;p&gt;This demonstrates the real power of Modules combined with Meta-Arguments.&lt;/p&gt;




&lt;h1&gt;
  
  
  📋 Reviewing the Plan with Multiple Module Instances
&lt;/h1&gt;

&lt;p&gt;After adding &lt;code&gt;for_each&lt;/code&gt;, I generated another execution plan.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform now displayed multiple module instances similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.servers["app"]

module.servers["worker"]

module.servers["cache"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This clearly showed that Terraform treats each module instance independently while still using the same reusable module definition.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔍 Inspecting the Infrastructure
&lt;/h1&gt;

&lt;p&gt;After deployment, I also explored Terraform's outputs and state to better understand how module resources are represented.&lt;/p&gt;

&lt;p&gt;Useful commands included:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform state list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.web_server.aws_instance.this
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This naming convention makes it easy to identify which resources belong to which module.&lt;/p&gt;




&lt;h1&gt;
  
  
  🍫 Bonus Exploration
&lt;/h1&gt;

&lt;p&gt;After completing the core module implementation, I explored a few advanced Terraform Module concepts that are commonly used in real-world DevOps projects.&lt;/p&gt;

&lt;p&gt;These bonus tasks helped me understand how teams build reusable infrastructure libraries, maintain module quality, and safely evolve infrastructure over time.&lt;/p&gt;

&lt;p&gt;Instead of focusing only on creating resources, these concepts emphasize writing modules that are reusable, maintainable, and production-ready.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 1 — Documenting the Module
&lt;/h1&gt;

&lt;p&gt;One of the best practices recommended in today's challenge was documenting every reusable module.&lt;/p&gt;

&lt;p&gt;A well-documented module allows other developers to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What the module does&lt;/li&gt;
&lt;li&gt;Required Inputs&lt;/li&gt;
&lt;li&gt;Optional Inputs&lt;/li&gt;
&lt;li&gt;Outputs&lt;/li&gt;
&lt;li&gt;Usage Examples&lt;/li&gt;
&lt;li&gt;Default Values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of reading the module source code, developers can simply open the module's &lt;code&gt;README.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My reusable EC2 module includes documentation describing its purpose, required inputs, optional parameters, outputs, and a usage example, making it much easier to consume in other projects. :contentReference[oaicite:0]{index=0}&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 2 — Input Validation
&lt;/h1&gt;

&lt;p&gt;Reusable modules should validate user inputs whenever possible.&lt;/p&gt;

&lt;p&gt;Terraform allows us to define validation rules inside &lt;code&gt;variables.tf&lt;/code&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"environment"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

  &lt;span class="nx"&gt;validation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"staging"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"prod"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;error_message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Environment must be dev, staging or prod."&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;Input Validation prevents invalid values from entering the module and reduces configuration mistakes.&lt;/p&gt;

&lt;p&gt;This makes reusable modules much safer for teams.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 3 — Publishing Modules using Git
&lt;/h1&gt;

&lt;p&gt;Terraform Modules don't have to remain inside the same repository.&lt;/p&gt;

&lt;p&gt;They can also be stored in a separate Git repository and reused across multiple projects.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"web_server"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"git::https://github.com/yourusername/terraform-aws-modules.git//ec2_instance?ref=v1.0.0"&lt;/span&gt;

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?ref=v1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;pins the module to a specific Git tag.&lt;/p&gt;

&lt;p&gt;Instead of downloading the latest code every time, Terraform always downloads the exact version.&lt;/p&gt;

&lt;p&gt;This improves stability and reproducibility.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 4 — Module Composition
&lt;/h1&gt;

&lt;p&gt;Another advanced concept introduced today was &lt;strong&gt;Module Composition&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of building one large module containing everything, Terraform encourages connecting multiple small modules together.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Networking Module

        │

        ▼

EC2 Module

        │

        ▼

Load Balancer Module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of one module becomes the input of another.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"network"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/network"&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"web"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/ec2_instance"&lt;/span&gt;

  &lt;span class="nx"&gt;subnet_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_subnet_id&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This creates highly modular and reusable Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;Instead of duplicating networking logic inside every EC2 module, the networking module provides the required outputs.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 5 — Why Modular Infrastructure Matters
&lt;/h1&gt;

&lt;p&gt;Today's challenge completely changed the way I think about Terraform projects.&lt;/p&gt;

&lt;p&gt;Without modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure becomes repetitive.&lt;/li&gt;
&lt;li&gt;Code duplication increases.&lt;/li&gt;
&lt;li&gt;Maintenance becomes difficult.&lt;/li&gt;
&lt;li&gt;Bugs are fixed in multiple places.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure becomes reusable.&lt;/li&gt;
&lt;li&gt;Updates happen in one place.&lt;/li&gt;
&lt;li&gt;Projects remain organized.&lt;/li&gt;
&lt;li&gt;Teams can share common infrastructure.&lt;/li&gt;
&lt;li&gt;Testing becomes much easier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why almost every production Terraform repository relies heavily on reusable modules.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧹 Cleaning Up the Infrastructure
&lt;/h1&gt;

&lt;p&gt;After verifying that everything was working correctly, I removed all the infrastructure created during today's challenge.&lt;/p&gt;

&lt;p&gt;Terraform makes cleanup just as simple as deployment.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Terraform displayed a confirmation prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you really want to destroy all resources?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After entering:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform removed every resource that had been created by the Root Module.&lt;/p&gt;

&lt;p&gt;Since the infrastructure itself was provisioned through the Child Module, Terraform automatically traversed the module hierarchy and destroyed all managed resources safely.&lt;/p&gt;

&lt;p&gt;Finally, Terraform displayed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destroy complete!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Destroying unused cloud resources is an important habit because it helps avoid unnecessary AWS costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg3nq6lqpc60oyt96lkru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg3nq6lqpc60oyt96lkru.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 What I Learned
&lt;/h1&gt;

&lt;p&gt;Day 5 introduced one of the most important Terraform concepts—&lt;strong&gt;Modules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Some of the key takeaways from today's challenge are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learned what Terraform Modules are.&lt;/li&gt;
&lt;li&gt;Understood the difference between Root Modules and Child Modules.&lt;/li&gt;
&lt;li&gt;Built my own reusable Local Module.&lt;/li&gt;
&lt;li&gt;Passed values into Modules using Variables.&lt;/li&gt;
&lt;li&gt;Returned useful information using Outputs.&lt;/li&gt;
&lt;li&gt;Learned why modules should receive IDs instead of performing their own lookups.&lt;/li&gt;
&lt;li&gt;Explored Local Modules, Registry Modules, and Git Modules.&lt;/li&gt;
&lt;li&gt;Understood different Module Version Pinning strategies.&lt;/li&gt;
&lt;li&gt;Used &lt;code&gt;for_each&lt;/code&gt; to instantiate multiple module instances.&lt;/li&gt;
&lt;li&gt;Explored Module Composition.&lt;/li&gt;
&lt;li&gt;Learned how documentation and validation improve module quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest lesson from today was understanding that Modules are the foundation of scalable Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;Instead of writing the same infrastructure repeatedly, we can package it once and reuse it across projects, environments, and teams.&lt;/p&gt;




&lt;h1&gt;
  
  
  📂 Repository Structure
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TerraWeek/
│
├── Day-01/
│   ├── README.md
│   └── ...
│
├── Day-02/
│   ├── README.md
│   └── ...
│
├── Day-03/
│   ├── README.md
│   └── ...
│
├── Day-04/
│   ├── README.md
│   └── ...
│
├── Day-05/
│   ├── main.tf
│   ├── outputs.tf
│   ├── terraform.tf
│   │
│   ├── modules/
│   │   └── ec2_instance/
│   │       ├── main.tf
│   │       ├── variables.tf
│   │       ├── outputs.tf
│   │       └── README.md
│   │
│   ├── README.md
│   └── images/
│
└── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🚀 Conclusion
&lt;/h1&gt;

&lt;p&gt;Day 5 marked an important shift in my Terraform journey.&lt;/p&gt;

&lt;p&gt;Until now, I had been focused on learning how to provision infrastructure.&lt;/p&gt;

&lt;p&gt;Today, I learned how to &lt;strong&gt;design reusable infrastructure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By separating the Root Module from reusable Child Modules, passing inputs through variables, exposing outputs, and organizing infrastructure into well-defined components, I gained a much better understanding of how production Terraform projects are structured.&lt;/p&gt;

&lt;p&gt;Exploring Registry Modules, Git Modules, Module Version Pinning, and Module Composition also gave me insight into how large teams build consistent, maintainable Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;With five days of the TerraWeek Challenge completed, I now have a much stronger foundation in writing Terraform that is not only functional but also reusable and scalable.&lt;/p&gt;

&lt;p&gt;I'm excited to continue the challenge and explore even more advanced Terraform concepts in the upcoming days.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏷️ Tags
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;#Terraform&lt;/code&gt; &lt;code&gt;#TerraformModules&lt;/code&gt; &lt;code&gt;#InfrastructureAsCode&lt;/code&gt; &lt;code&gt;#AWS&lt;/code&gt; &lt;code&gt;#DevOps&lt;/code&gt; &lt;code&gt;#CloudComputing&lt;/code&gt; &lt;code&gt;#Automation&lt;/code&gt; &lt;code&gt;#PlatformEngineering&lt;/code&gt; &lt;code&gt;#CloudEngineering&lt;/code&gt; &lt;code&gt;#LearnInPublic&lt;/code&gt; &lt;code&gt;#TrainWithShubham&lt;/code&gt; &lt;code&gt;#TerraWeekChallenge&lt;/code&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🌱 TerraWeek Challenge – Day 4 : Terraform State &amp; Remote Backends (Native Locking)</title>
      <dc:creator>Kshitij Sharma</dc:creator>
      <pubDate>Wed, 15 Jul 2026 11:55:00 +0000</pubDate>
      <link>https://dev.to/kshitij_sharma_fd33fdb032/terraweek-challenge-day-4-terraform-state-remote-backends-native-locking-2dhp</link>
      <guid>https://dev.to/kshitij_sharma_fd33fdb032/terraweek-challenge-day-4-terraform-state-remote-backends-native-locking-2dhp</guid>
      <description>&lt;p&gt;📅 &lt;strong&gt;Date:&lt;/strong&gt; 15 July 2026&lt;/p&gt;

&lt;p&gt;Welcome to &lt;strong&gt;Day 4&lt;/strong&gt; of my &lt;strong&gt;TerraWeek Challenge!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;p&gt;After spending the previous three days learning Terraform fundamentals, HCL, Variables, Providers, Resources, and provisioning cloud infrastructure on AWS, today's challenge introduced one of the most important concepts in Terraform—&lt;strong&gt;State Management&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Creating infrastructure is only one part of Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;Managing that infrastructure safely over time is where Terraform State becomes essential.&lt;/p&gt;

&lt;p&gt;Today's challenge focused on understanding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Terraform State is&lt;/li&gt;
&lt;li&gt;Why Terraform needs a State File&lt;/li&gt;
&lt;li&gt;Why the State File is considered sensitive&lt;/li&gt;
&lt;li&gt;Local vs Remote State&lt;/li&gt;
&lt;li&gt;Remote Backends using Amazon S3&lt;/li&gt;
&lt;li&gt;Native State Locking using &lt;code&gt;use_lockfile&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;State Commands&lt;/li&gt;
&lt;li&gt;Importing Existing Infrastructure into Terraform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One interesting thing I learned today is that almost every professional Terraform project stores its state remotely instead of keeping it locally.&lt;/p&gt;

&lt;p&gt;Remote State makes collaboration easier, prevents accidental conflicts, and keeps infrastructure management much safer.&lt;/p&gt;

&lt;p&gt;By the end of today's challenge, I understood why Terraform State is often called &lt;strong&gt;the brain of Terraform&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  📚 Learning Objectives
&lt;/h1&gt;

&lt;p&gt;By the end of Day 4, I was able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand what Terraform State is.&lt;/li&gt;
&lt;li&gt;Learn why Terraform maintains a State File.&lt;/li&gt;
&lt;li&gt;Understand the importance of State Management.&lt;/li&gt;
&lt;li&gt;Learn why Terraform State should never be committed to Git.&lt;/li&gt;
&lt;li&gt;Understand State Drift.&lt;/li&gt;
&lt;li&gt;Explore Terraform State Commands.&lt;/li&gt;
&lt;li&gt;Learn the difference between Local and Remote State.&lt;/li&gt;
&lt;li&gt;Configure an Amazon S3 Backend.&lt;/li&gt;
&lt;li&gt;Understand Native State Locking using &lt;code&gt;use_lockfile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Bootstrap backend infrastructure.&lt;/li&gt;
&lt;li&gt;Migrate Local State to Remote State.&lt;/li&gt;
&lt;li&gt;Import existing resources into Terraform State.&lt;/li&gt;
&lt;li&gt;Explore advanced State Management features.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  📂 Project Structure
&lt;/h1&gt;

&lt;p&gt;Today's challenge was slightly different from the previous days.&lt;/p&gt;

&lt;p&gt;Instead of working with a single Terraform project, the assignment was divided into two separate directories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Day-04/
│
├── backend_demo/
│   ├── terraform.tf
│   └── resources.tf
│
├── backend_infra/
│   ├── terraform.tf
│   ├── resources.tf
│   ├── variables.tf
│   └── outputs.tf
│
├── README.md
└── images/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each folder serves a completely different purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  📁 backend_infra
&lt;/h2&gt;

&lt;p&gt;This directory is responsible for creating the infrastructure required to store the Terraform State.&lt;/p&gt;

&lt;p&gt;It provisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon S3 Bucket&lt;/li&gt;
&lt;li&gt;Bucket Versioning&lt;/li&gt;
&lt;li&gt;Bucket Encryption&lt;/li&gt;
&lt;li&gt;Other backend-related resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important thing to remember is that this folder itself uses &lt;strong&gt;Local State&lt;/strong&gt; because the backend must exist before Terraform can store its state remotely.&lt;/p&gt;




&lt;h2&gt;
  
  
  📁 backend_demo
&lt;/h2&gt;

&lt;p&gt;Once the backend infrastructure is created, this directory demonstrates how Terraform uses that S3 bucket as its Remote Backend.&lt;/p&gt;

&lt;p&gt;Instead of storing the state file locally, Terraform uploads it directly to Amazon S3.&lt;/p&gt;

&lt;p&gt;This simulates how Terraform projects are managed in real production environments.&lt;/p&gt;




&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpj3tsg8076vzp5pfwc0m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpj3tsg8076vzp5pfwc0m.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ Prerequisites
&lt;/h1&gt;

&lt;p&gt;Before starting today's challenge, I ensured that the following tools were installed and configured.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform&lt;/li&gt;
&lt;li&gt;AWS CLI&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;li&gt;AWS Account&lt;/li&gt;
&lt;li&gt;Amazon S3 Permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since today's project interacts with AWS, the AWS CLI must already be configured with valid credentials.&lt;/p&gt;

&lt;p&gt;Unlike previous days, this challenge also requires permissions to create and manage Amazon S3 buckets.&lt;/p&gt;




&lt;h1&gt;
  
  
  🛠 Verifying Terraform Installation
&lt;/h1&gt;

&lt;p&gt;Before creating any infrastructure, I verified the installed Terraform version.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Terraform displayed the currently installed version along with provider compatibility information.&lt;/p&gt;

&lt;p&gt;Verifying the version beforehand helps ensure compatibility with newer features such as &lt;strong&gt;Native S3 State Locking&lt;/strong&gt;, which is available in recent Terraform releases.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp6d2lln7snuznpvgnp2o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp6d2lln7snuznpvgnp2o.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ☁️ Verifying AWS CLI Configuration
&lt;/h1&gt;

&lt;p&gt;Since Terraform communicates with AWS through the AWS Provider, it is important to verify that AWS credentials are configured correctly.&lt;/p&gt;

&lt;p&gt;I confirmed my identity using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws sts get-caller-identity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Account ID&lt;/li&gt;
&lt;li&gt;User ARN&lt;/li&gt;
&lt;li&gt;User ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Receiving a successful response confirms that Terraform will be able to authenticate with AWS.&lt;/p&gt;

&lt;p&gt;It is always a good practice to verify authentication before provisioning infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3bvx9dregfzm7hxfkqve.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3bvx9dregfzm7hxfkqve.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🗄️ What is Terraform State?
&lt;/h1&gt;

&lt;p&gt;Terraform State is a file that stores information about every resource Terraform manages.&lt;/p&gt;

&lt;p&gt;Whenever Terraform creates infrastructure, it records important information inside the &lt;strong&gt;terraform.tfstate&lt;/strong&gt; file.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Resource IDs&lt;/li&gt;
&lt;li&gt;Metadata&lt;/li&gt;
&lt;li&gt;Dependencies&lt;/li&gt;
&lt;li&gt;Current Configuration&lt;/li&gt;
&lt;li&gt;Resource Attributes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform uses this file to compare the &lt;strong&gt;current state&lt;/strong&gt; of infrastructure with the &lt;strong&gt;desired state&lt;/strong&gt; described in the Terraform configuration.&lt;/p&gt;

&lt;p&gt;Without the State File, Terraform would have no way of knowing which resources already exist.&lt;/p&gt;

&lt;p&gt;This is why the State File is considered the heart of every Terraform project.&lt;/p&gt;




&lt;h1&gt;
  
  
  🤔 Why Does Terraform Need State?
&lt;/h1&gt;

&lt;p&gt;Imagine creating an EC2 Instance today.&lt;/p&gt;

&lt;p&gt;Tomorrow, you modify the instance type.&lt;/p&gt;

&lt;p&gt;How does Terraform know that the instance already exists?&lt;/p&gt;

&lt;p&gt;The answer is simple.&lt;/p&gt;

&lt;p&gt;Terraform checks the &lt;strong&gt;State File&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of creating a brand-new EC2 instance every time, Terraform compares the desired configuration with the recorded state and determines exactly what needs to change.&lt;/p&gt;

&lt;p&gt;Because of this comparison, Terraform can safely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create resources&lt;/li&gt;
&lt;li&gt;Update resources&lt;/li&gt;
&lt;li&gt;Destroy resources&lt;/li&gt;
&lt;li&gt;Detect infrastructure changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without State, Terraform would behave as if every deployment were the first deployment.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔐 Why is Terraform State Sensitive?
&lt;/h1&gt;

&lt;p&gt;One of the most surprising things I learned today was that the Terraform State File may contain confidential information.&lt;/p&gt;

&lt;p&gt;Depending on the infrastructure, it may store:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passwords&lt;/li&gt;
&lt;li&gt;Database Connection Strings&lt;/li&gt;
&lt;li&gt;API Keys&lt;/li&gt;
&lt;li&gt;Access Tokens&lt;/li&gt;
&lt;li&gt;Resource IDs&lt;/li&gt;
&lt;li&gt;Internal Metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although Terraform marks sensitive variables in outputs, the actual values can still exist inside the State File.&lt;/p&gt;

&lt;p&gt;Because of this, the State File should never be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edited manually&lt;/li&gt;
&lt;li&gt;Shared publicly&lt;/li&gt;
&lt;li&gt;Committed to Git&lt;/li&gt;
&lt;li&gt;Stored in unsecured locations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Professional teams usually store Terraform State inside secure Remote Backends such as Amazon S3 with encryption enabled.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌍 Local State vs Remote State
&lt;/h1&gt;

&lt;p&gt;Terraform supports two approaches for storing the State File.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local State
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The State File remains on the developer's local machine.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple&lt;/li&gt;
&lt;li&gt;Easy to use&lt;/li&gt;
&lt;li&gt;Great for learning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Difficult for teams&lt;/li&gt;
&lt;li&gt;Easy to lose&lt;/li&gt;
&lt;li&gt;No locking&lt;/li&gt;
&lt;li&gt;No centralized storage&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Remote State
&lt;/h2&gt;

&lt;p&gt;The State File is stored inside a remote storage service.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Amazon S3&lt;/li&gt;
&lt;li&gt;HCP Terraform (Terraform Cloud)&lt;/li&gt;
&lt;li&gt;Azure Storage&lt;/li&gt;
&lt;li&gt;Google Cloud Storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Centralized storage&lt;/li&gt;
&lt;li&gt;Team collaboration&lt;/li&gt;
&lt;li&gt;Better security&lt;/li&gt;
&lt;li&gt;Automatic backups&lt;/li&gt;
&lt;li&gt;State locking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For production environments, Remote State is the recommended approach.&lt;/p&gt;

&lt;p&gt;Today's assignment focused on using &lt;strong&gt;Amazon S3&lt;/strong&gt; as the Remote Backend with &lt;strong&gt;Native State Locking&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🗂️ Understanding the Terraform State File
&lt;/h1&gt;

&lt;p&gt;In the previous section, I learned why Terraform State is one of the most critical components of every Terraform project.&lt;/p&gt;

&lt;p&gt;However, simply knowing what the State File is isn't enough.&lt;/p&gt;

&lt;p&gt;To work efficiently with Terraform, it's important to understand how Terraform interacts with the State File, how we can inspect it, and how we can safely manage it over time.&lt;/p&gt;

&lt;p&gt;Terraform provides several built-in commands that allow us to inspect, move, rename, remove, and visualize resources stored inside the State File.&lt;/p&gt;

&lt;p&gt;These commands become extremely useful while maintaining production infrastructure.&lt;/p&gt;




&lt;h1&gt;
  
  
  📄 What Does the State File Contain?
&lt;/h1&gt;

&lt;p&gt;Every time Terraform provisions infrastructure, it records important information inside the &lt;code&gt;terraform.tfstate&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The State File stores details such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource IDs&lt;/li&gt;
&lt;li&gt;Current Infrastructure&lt;/li&gt;
&lt;li&gt;Dependencies&lt;/li&gt;
&lt;li&gt;Metadata&lt;/li&gt;
&lt;li&gt;Resource Attributes&lt;/li&gt;
&lt;li&gt;Provider Information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform uses this information to compare the desired configuration with the existing infrastructure before making any changes.&lt;/p&gt;

&lt;p&gt;This comparison is what makes Terraform idempotent and reliable.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚠️ Never Edit the State File Manually
&lt;/h1&gt;

&lt;p&gt;One of the biggest lessons from today's challenge was understanding that the Terraform State File should &lt;strong&gt;never&lt;/strong&gt; be edited manually.&lt;/p&gt;

&lt;p&gt;Although it is stored as a JSON file, manually changing its contents can corrupt the state and cause Terraform to lose track of managed resources.&lt;/p&gt;

&lt;p&gt;Instead of editing the file directly, Terraform provides dedicated commands to safely manipulate the State.&lt;/p&gt;

&lt;p&gt;This ensures that the infrastructure remains consistent and predictable.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌪️ Understanding State Drift
&lt;/h1&gt;

&lt;p&gt;Infrastructure doesn't always change through Terraform.&lt;/p&gt;

&lt;p&gt;Sometimes resources are modified manually through the AWS Console or another tool.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Someone changes an EC2 instance type manually.&lt;/li&gt;
&lt;li&gt;A Security Group rule is updated directly in AWS.&lt;/li&gt;
&lt;li&gt;An S3 bucket policy is modified outside Terraform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These unexpected changes create a mismatch between the &lt;strong&gt;actual infrastructure&lt;/strong&gt; and the &lt;strong&gt;Terraform State&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This situation is called &lt;strong&gt;State Drift&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Terraform detects these differences during:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

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

&lt;/div&gt;



&lt;p&gt;Detecting State Drift early helps prevent unexpected infrastructure changes during future deployments.&lt;/p&gt;




&lt;h1&gt;
  
  
  🛠️ Exploring Terraform State Commands
&lt;/h1&gt;

&lt;p&gt;Terraform provides several commands for inspecting and managing the State File.&lt;/p&gt;

&lt;p&gt;Instead of modifying the State manually, these commands should always be used.&lt;/p&gt;

&lt;p&gt;Let's explore the most important ones.&lt;/p&gt;




&lt;h1&gt;
  
  
  📋 &lt;code&gt;terraform state list&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;This command lists every resource currently managed by Terraform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform state list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws_s3_bucket.tf_state

aws_s3_bucket_versioning.versioning

aws_s3_bucket_server_side_encryption_configuration.encryption
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command is particularly useful when working with large Terraform projects because it provides a quick overview of all managed resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwpewe7kugnqviwp8j9it.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwpewe7kugnqviwp8j9it.png" alt=" " width="799" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🔍 &lt;code&gt;terraform state show&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Sometimes we need detailed information about a specific resource.&lt;/p&gt;

&lt;p&gt;Terraform provides the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform state show aws_s3_bucket.tf_state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This displays detailed information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bucket Name&lt;/li&gt;
&lt;li&gt;ARN&lt;/li&gt;
&lt;li&gt;Region&lt;/li&gt;
&lt;li&gt;Encryption&lt;/li&gt;
&lt;li&gt;Versioning&lt;/li&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike &lt;code&gt;terraform show&lt;/code&gt;, this command focuses on a single resource.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzljhkpkscvbcytsrzney.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzljhkpkscvbcytsrzney.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 &lt;code&gt;terraform state mv&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;As Terraform projects grow, resources are often renamed or reorganized.&lt;/p&gt;

&lt;p&gt;Instead of destroying and recreating infrastructure, Terraform allows us to move resource addresses inside the State File.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform state &lt;span class="nb"&gt;mv &lt;/span&gt;aws_s3_bucket.old aws_s3_bucket.new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command updates the Terraform State without modifying the actual AWS resource.&lt;/p&gt;

&lt;p&gt;It is extremely useful while refactoring Terraform configurations.&lt;/p&gt;




&lt;h1&gt;
  
  
  ❌ &lt;code&gt;terraform state rm&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Sometimes we want Terraform to stop managing a resource without deleting it.&lt;/p&gt;

&lt;p&gt;For that purpose, Terraform provides:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform state &lt;span class="nb"&gt;rm &lt;/span&gt;aws_s3_bucket.tf_state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command removes the resource from the State File only.&lt;/p&gt;

&lt;p&gt;The actual AWS resource continues to exist.&lt;/p&gt;

&lt;p&gt;This is useful when migrating infrastructure or handing resource management to another Terraform project.&lt;/p&gt;




&lt;h1&gt;
  
  
  📖 &lt;code&gt;terraform show&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Terraform also allows us to display the current infrastructure in a human-readable format.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;This command displays:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;li&gt;Attributes&lt;/li&gt;
&lt;li&gt;Dependencies&lt;/li&gt;
&lt;li&gt;Outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike opening the JSON State File manually, &lt;code&gt;terraform show&lt;/code&gt; presents the information in a much cleaner and easier-to-read format.&lt;/p&gt;




&lt;h1&gt;
  
  
  ☁️ Understanding Remote Backends
&lt;/h1&gt;

&lt;p&gt;Up until now, all Terraform State Files were stored locally.&lt;/p&gt;

&lt;p&gt;While this works well for learning and personal projects, it creates several challenges in team environments.&lt;/p&gt;

&lt;p&gt;Some common problems include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple developers maintaining different State Files.&lt;/li&gt;
&lt;li&gt;Risk of accidentally deleting the State.&lt;/li&gt;
&lt;li&gt;No centralized storage.&lt;/li&gt;
&lt;li&gt;No State Locking.&lt;/li&gt;
&lt;li&gt;Difficult collaboration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To solve these issues, Terraform supports &lt;strong&gt;Remote Backends&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A Remote Backend stores the State File in a centralized location that can be accessed safely by multiple team members.&lt;/p&gt;

&lt;p&gt;Some commonly used Remote Backends include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon S3&lt;/li&gt;
&lt;li&gt;HCP Terraform (Terraform Cloud)&lt;/li&gt;
&lt;li&gt;Azure Storage&lt;/li&gt;
&lt;li&gt;Google Cloud Storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Today's assignment focused on using &lt;strong&gt;Amazon S3&lt;/strong&gt; as the Remote Backend.&lt;/p&gt;




&lt;h1&gt;
  
  
  🪣 Why Amazon S3?
&lt;/h1&gt;

&lt;p&gt;Amazon S3 is one of the most widely used Remote Backends for Terraform.&lt;/p&gt;

&lt;p&gt;Some of its advantages include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highly Durable&lt;/li&gt;
&lt;li&gt;Secure&lt;/li&gt;
&lt;li&gt;Centralized&lt;/li&gt;
&lt;li&gt;Versioning Support&lt;/li&gt;
&lt;li&gt;Encryption Support&lt;/li&gt;
&lt;li&gt;Easy Team Collaboration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By storing the State File in S3, every team member works with the same infrastructure state.&lt;/p&gt;

&lt;p&gt;This significantly reduces deployment conflicts.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔒 Native State Locking
&lt;/h1&gt;

&lt;p&gt;One of the biggest updates introduced in recent Terraform versions is &lt;strong&gt;Native S3 State Locking&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Older Terraform versions required &lt;strong&gt;DynamoDB&lt;/strong&gt; to prevent multiple users from modifying the same State File simultaneously.&lt;/p&gt;

&lt;p&gt;Modern Terraform versions simplify this process using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;use_lockfile&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables native locking directly within Amazon S3, eliminating the need for DynamoDB.&lt;/p&gt;

&lt;p&gt;Whenever Terraform performs an operation such as &lt;code&gt;apply&lt;/code&gt;, it temporarily creates a &lt;code&gt;.tflock&lt;/code&gt; file inside the S3 bucket.&lt;/p&gt;

&lt;p&gt;Once the operation finishes successfully, the lock file is automatically removed.&lt;/p&gt;

&lt;p&gt;This prevents concurrent modifications to the same State File and makes team collaboration much safer.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏗️ Bootstrapping the Backend Infrastructure
&lt;/h1&gt;

&lt;p&gt;Before Terraform can store its State remotely, the Remote Backend itself must already exist.&lt;/p&gt;

&lt;p&gt;This creates an interesting challenge:&lt;/p&gt;

&lt;p&gt;How can Terraform store its State inside an S3 bucket that hasn't been created yet?&lt;/p&gt;

&lt;p&gt;The solution is called &lt;strong&gt;Bootstrapping&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;backend_infra&lt;/code&gt; project is responsible for creating:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3 Bucket&lt;/li&gt;
&lt;li&gt;Versioning&lt;/li&gt;
&lt;li&gt;Encryption&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the bucket doesn't exist initially, this project temporarily uses &lt;strong&gt;Local State&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once the S3 bucket is available, other Terraform projects can safely migrate their State into it.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ Configuring the S3 Backend
&lt;/h1&gt;

&lt;p&gt;After creating the backend infrastructure, the next step is configuring the backend.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your-terraform-state-bucket"&lt;/span&gt;

    &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"day04/terraform.tfstate"&lt;/span&gt;

    &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;

    &lt;span class="nx"&gt;encrypt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="nx"&gt;use_lockfile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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 instructs Terraform to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store the State File in Amazon S3.&lt;/li&gt;
&lt;li&gt;Encrypt the State File.&lt;/li&gt;
&lt;li&gt;Enable Native State Locking.&lt;/li&gt;
&lt;li&gt;Maintain a centralized State for the project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once configured, Terraform automatically offers to migrate the existing Local State to the Remote Backend during initialization.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Bootstrapping the Remote Backend
&lt;/h1&gt;

&lt;p&gt;After understanding Terraform State and Remote Backends, it was finally time to implement everything practically.&lt;/p&gt;

&lt;p&gt;Unlike the previous days, today's practical was divided into &lt;strong&gt;two separate Terraform projects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The first project creates the backend infrastructure, while the second project uses that infrastructure as its Remote Backend.&lt;/p&gt;

&lt;p&gt;The workflow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backend_infra
      │
      ▼
Create S3 Bucket
      │
      ▼
Configure Remote Backend
      │
      ▼
Migrate Local State → Amazon S3
      │
      ▼
Verify Remote State
      │
      ▼
Explore State Commands
      │
      ▼
Import Existing Resources
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This two-step approach is called &lt;strong&gt;Bootstrapping&lt;/strong&gt;, and it's the standard way of creating Terraform backends in production.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏗️ Step 1 — Create the Backend Infrastructure
&lt;/h1&gt;

&lt;p&gt;The very first step was creating the infrastructure that would later store the Terraform State.&lt;/p&gt;

&lt;p&gt;I navigated to the &lt;strong&gt;backend_infra&lt;/strong&gt; directory.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This project is responsible for creating:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon S3 Bucket&lt;/li&gt;
&lt;li&gt;Bucket Versioning&lt;/li&gt;
&lt;li&gt;Server-Side Encryption&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this stage, Terraform still uses &lt;strong&gt;Local State&lt;/strong&gt;, because the backend doesn't exist yet.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Step 2 — Initialize Backend Infrastructure
&lt;/h1&gt;

&lt;p&gt;Once inside the &lt;code&gt;backend_infra&lt;/code&gt; directory, I initialized Terraform.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform downloaded the required AWS Provider and initialized the working directory.&lt;/p&gt;

&lt;p&gt;During initialization, Terraform created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.terraform/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.terraform.lock.hcl&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the initialization completed successfully, Terraform displayed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Terraform has been successfully initialized!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgx01bcy8oym8cu3qqcm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgx01bcy8oym8cu3qqcm7.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📋 Step 3 — Create the S3 Backend
&lt;/h1&gt;

&lt;p&gt;After initialization, I provisioned the backend infrastructure.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform displayed the execution plan, listing all the S3-related resources it was about to create.&lt;/p&gt;

&lt;p&gt;These resources included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3 Bucket&lt;/li&gt;
&lt;li&gt;Bucket Versioning&lt;/li&gt;
&lt;li&gt;Bucket Encryption&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After reviewing the execution plan, I confirmed the deployment.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform created the backend infrastructure successfully.&lt;/p&gt;

&lt;p&gt;Once completed, the S3 bucket was ready to store Terraform State.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foqochre9a0drm0cm3z5f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foqochre9a0drm0cm3z5f.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🪣 Verifying the S3 Bucket
&lt;/h1&gt;

&lt;p&gt;After the deployment completed successfully, I opened the AWS Management Console to verify that the backend infrastructure had been created.&lt;/p&gt;

&lt;p&gt;Inside the Amazon S3 Console, I confirmed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The S3 Bucket was created.&lt;/li&gt;
&lt;li&gt;Versioning was enabled.&lt;/li&gt;
&lt;li&gt;Server-Side Encryption was enabled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This bucket will now act as the centralized location for storing Terraform State.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4c1tu9bmecpxro49lleq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4c1tu9bmecpxro49lleq.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 Step 4 — Configure the Remote Backend
&lt;/h1&gt;

&lt;p&gt;Once the backend infrastructure was available, I moved to the second project.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Unlike &lt;code&gt;backend_infra&lt;/code&gt;, this project contains the Remote Backend configuration.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;terraform.tf&lt;/code&gt; file points Terraform to the S3 bucket created earlier.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-terraform-state-bucket"&lt;/span&gt;

    &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"day04/terraform.tfstate"&lt;/span&gt;

    &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;

    &lt;span class="nx"&gt;encrypt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="nx"&gt;use_lockfile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;The most important addition here is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;use_lockfile&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables &lt;strong&gt;Native S3 State Locking&lt;/strong&gt;, eliminating the need for DynamoDB.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Step 5 — Initialize the Remote Backend
&lt;/h1&gt;

&lt;p&gt;After configuring the backend, I initialized Terraform again.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This time Terraform detected an existing Local State and asked whether it should migrate the State to Amazon S3.&lt;/p&gt;

&lt;p&gt;Terraform displayed a message similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you want to copy existing state to the new backend?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;/div&gt;



&lt;p&gt;Terraform then uploaded the existing Local State to the S3 bucket.&lt;/p&gt;

&lt;p&gt;This completed the migration from Local State to Remote State.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3gvtgagowo0jc7aw6yoc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3gvtgagowo0jc7aw6yoc.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ☁️ Verifying Remote State
&lt;/h1&gt;

&lt;p&gt;After the migration completed, I opened the Amazon S3 Console again.&lt;/p&gt;

&lt;p&gt;Inside the bucket, I verified that Terraform had uploaded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirmed that Terraform was now using &lt;strong&gt;Remote State&lt;/strong&gt; instead of Local State.&lt;/p&gt;

&lt;p&gt;From this point onward, every Terraform operation updates the State File directly inside Amazon S3.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flp81yls5qg1375pe8iya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flp81yls5qg1375pe8iya.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🔒 Verifying Native State Locking
&lt;/h1&gt;

&lt;p&gt;One of the biggest improvements in modern Terraform is Native State Locking.&lt;/p&gt;

&lt;p&gt;Whenever Terraform executes commands such as:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform temporarily creates a lock file inside the S3 bucket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform.tfstate.tflock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lock file prevents multiple users from modifying the State File simultaneously.&lt;/p&gt;

&lt;p&gt;After Terraform completes the operation successfully, the lock file is removed automatically.&lt;/p&gt;

&lt;p&gt;Watching the &lt;code&gt;.tflock&lt;/code&gt; file appear and disappear during deployment demonstrated how Terraform safely prevents concurrent updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh74riwqxk8ev3cvxvddb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh74riwqxk8ev3cvxvddb.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📤 Viewing Terraform Outputs
&lt;/h1&gt;

&lt;p&gt;Once the backend was fully configured, I viewed the output values generated by Terraform.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Depending on the configuration, Terraform displayed useful information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bucket Name&lt;/li&gt;
&lt;li&gt;Bucket ARN&lt;/li&gt;
&lt;li&gt;Region&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Outputs provide a convenient way to access infrastructure details without manually searching through the AWS Console.&lt;/p&gt;




&lt;h1&gt;
  
  
  📥 Importing Existing Resources
&lt;/h1&gt;

&lt;p&gt;Another important feature introduced in today's challenge was the &lt;strong&gt;Import Block&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sometimes cloud resources already exist because they were created manually.&lt;/p&gt;

&lt;p&gt;Instead of recreating them, Terraform allows us to import those resources into the State File.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imported&lt;/span&gt;

  &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-existing-bucket"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform then generates the configuration automatically using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform plan &lt;span class="nt"&gt;-generate-config-out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;generated.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated configuration can be reviewed and integrated into the existing project.&lt;/p&gt;

&lt;p&gt;Import Blocks make it much easier to bring manually created infrastructure under Terraform management.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffz20a0e2j5cvmw5u9ms8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffz20a0e2j5cvmw5u9ms8.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🍫 Bonus Exploration
&lt;/h1&gt;

&lt;p&gt;After completing the core tasks, I explored a few additional Terraform features that are commonly used in production environments.&lt;/p&gt;

&lt;p&gt;Although these tasks were optional, they provided a much deeper understanding of how Terraform manages infrastructure safely and efficiently across teams.&lt;/p&gt;

&lt;p&gt;These bonus exercises focused on improving state management, collaboration, and infrastructure refactoring.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 1 — Comparing Remote Backends
&lt;/h1&gt;

&lt;p&gt;Terraform supports multiple Remote Backends for storing the State File.&lt;/p&gt;

&lt;p&gt;Although I implemented &lt;strong&gt;Amazon S3&lt;/strong&gt; in this challenge, I also explored some other popular backend options.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Backend&lt;/th&gt;
&lt;th&gt;Best Use Case&lt;/th&gt;
&lt;th&gt;Locking Support&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Amazon S3&lt;/td&gt;
&lt;td&gt;AWS Workloads&lt;/td&gt;
&lt;td&gt;✅ Native (&lt;code&gt;use_lockfile&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Most widely used in AWS environments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HCP Terraform (Terraform Cloud)&lt;/td&gt;
&lt;td&gt;Teams &amp;amp; Enterprises&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;Remote runs, policies, collaboration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure Storage&lt;/td&gt;
&lt;td&gt;Azure Workloads&lt;/td&gt;
&lt;td&gt;✅ Supported&lt;/td&gt;
&lt;td&gt;Best for Microsoft Azure users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Cloud Storage (GCS)&lt;/td&gt;
&lt;td&gt;Google Cloud&lt;/td&gt;
&lt;td&gt;✅ Supported&lt;/td&gt;
&lt;td&gt;Ideal for GCP-based projects&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For AWS-based infrastructure, Amazon S3 remains one of the most popular choices because it is highly durable, secure, and integrates seamlessly with Terraform.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 2 — S3 Bucket Versioning
&lt;/h1&gt;

&lt;p&gt;One of the biggest advantages of storing Terraform State in Amazon S3 is &lt;strong&gt;Bucket Versioning&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of replacing the existing State File every time Terraform performs an operation, Amazon S3 preserves older versions automatically.&lt;/p&gt;

&lt;p&gt;This provides several benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recovery from accidental deletion&lt;/li&gt;
&lt;li&gt;Rollback to previous State versions&lt;/li&gt;
&lt;li&gt;Better auditing&lt;/li&gt;
&lt;li&gt;Improved disaster recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the latest State File becomes corrupted or is deleted accidentally, an earlier version can be restored directly from the S3 Console.&lt;/p&gt;

&lt;p&gt;This significantly improves the reliability of Infrastructure as Code projects.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 3 — Understanding the &lt;code&gt;moved&lt;/code&gt; Block
&lt;/h1&gt;

&lt;p&gt;As Terraform projects evolve, resources are often renamed or reorganized.&lt;/p&gt;

&lt;p&gt;Normally, renaming a resource causes Terraform to destroy the old resource and create a new one.&lt;/p&gt;

&lt;p&gt;To avoid this unnecessary recreation, Terraform provides the &lt;strong&gt;&lt;code&gt;moved&lt;/code&gt; block&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;moved&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;old_bucket&lt;/span&gt;

  &lt;span class="nx"&gt;to&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state_bucket&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Instead of recreating the infrastructure, Terraform updates the resource address inside the State File.&lt;/p&gt;

&lt;p&gt;This makes refactoring Terraform configurations much safer.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 4 — Understanding the &lt;code&gt;removed&lt;/code&gt; Block
&lt;/h1&gt;

&lt;p&gt;Sometimes we want Terraform to stop managing a resource without actually deleting it.&lt;/p&gt;

&lt;p&gt;Terraform provides the &lt;strong&gt;&lt;code&gt;removed&lt;/code&gt; block&lt;/strong&gt; for this purpose.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;removed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logs&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Using a &lt;code&gt;removed&lt;/code&gt; block removes the resource from Terraform State while leaving the actual infrastructure untouched.&lt;/p&gt;

&lt;p&gt;This is particularly useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Migrating resources to another Terraform project&lt;/li&gt;
&lt;li&gt;Handing resource management to another team&lt;/li&gt;
&lt;li&gt;Removing resources from Terraform without deleting production infrastructure&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 5 — Continuous Health Checks using &lt;code&gt;check&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Modern Terraform also supports &lt;strong&gt;Check Blocks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These blocks allow Terraform to validate infrastructure continuously.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;check&lt;/span&gt; &lt;span class="s2"&gt;"bucket_versioning_enabled"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="nx"&gt;error_message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Bucket versioning must remain enabled."&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;Unlike validation rules, Check Blocks evaluate infrastructure after deployment.&lt;/p&gt;

&lt;p&gt;They help detect configuration drift and ensure important infrastructure requirements continue to be satisfied.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧹 Cleaning Up the Infrastructure
&lt;/h1&gt;

&lt;p&gt;After verifying that everything was working correctly, I removed all the infrastructure created during today's challenge.&lt;/p&gt;

&lt;p&gt;Since two separate Terraform projects were used, cleanup also happened in two stages.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1 — Destroy the Demo Infrastructure
&lt;/h2&gt;

&lt;p&gt;First, I navigated to the &lt;code&gt;backend_demo&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then I destroyed the demo resources.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform displayed a confirmation prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you really want to destroy all resources?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After entering:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform removed every resource managed by the demo project.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fomqd5ox7e4vxydkjf71a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fomqd5ox7e4vxydkjf71a.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2 — Destroy the Backend Infrastructure
&lt;/h2&gt;

&lt;p&gt;Once the demo resources were removed, I switched to the backend infrastructure project.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Since the S3 bucket contained multiple versions of the Terraform State File, I first ensured that the bucket was empty.&lt;/p&gt;

&lt;p&gt;After clearing the bucket, I executed:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform successfully removed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3 Bucket&lt;/li&gt;
&lt;li&gt;Bucket Versioning&lt;/li&gt;
&lt;li&gt;Bucket Encryption Configuration&lt;/li&gt;
&lt;li&gt;Other backend resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This completed the cleanup process.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fllp2f5tco6jvkorbhn4u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fllp2f5tco6jvkorbhn4u.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 What I Learned
&lt;/h1&gt;

&lt;p&gt;Day 4 introduced one of the most important concepts in Terraform—&lt;strong&gt;State Management&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Some of the key takeaways from today's challenge are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learned what the Terraform State File is and why it exists.&lt;/li&gt;
&lt;li&gt;Understood why Terraform State should never be edited manually.&lt;/li&gt;
&lt;li&gt;Explored Terraform State Commands.&lt;/li&gt;
&lt;li&gt;Learned the concept of State Drift.&lt;/li&gt;
&lt;li&gt;Understood why Terraform State is considered sensitive.&lt;/li&gt;
&lt;li&gt;Learned the difference between Local State and Remote State.&lt;/li&gt;
&lt;li&gt;Bootstrapped backend infrastructure using Terraform.&lt;/li&gt;
&lt;li&gt;Configured Amazon S3 as a Remote Backend.&lt;/li&gt;
&lt;li&gt;Enabled Native State Locking using &lt;code&gt;use_lockfile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Migrated Local State to Remote State.&lt;/li&gt;
&lt;li&gt;Imported existing infrastructure into Terraform State.&lt;/li&gt;
&lt;li&gt;Explored advanced features such as &lt;code&gt;moved&lt;/code&gt;, &lt;code&gt;removed&lt;/code&gt;, and &lt;code&gt;check&lt;/code&gt; blocks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest lesson from today's challenge was understanding that Infrastructure as Code isn't only about creating resources—it is equally about managing them safely throughout their entire lifecycle.&lt;/p&gt;




&lt;h1&gt;
  
  
  📂 Repository Structure
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TerraWeek/
│
├── Day-01/
│   ├── README.md
│   └── ...
│
├── Day-02/
│   ├── README.md
│   └── ...
│
├── Day-03/
│   ├── README.md
│   └── ...
│
├── Day-04/
│   ├── backend_demo/
│   │   ├── terraform.tf
│   │   └── resources.tf
│   │
│   ├── backend_infra/
│   │   ├── terraform.tf
│   │   ├── resources.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   │
│   ├── README.md
│   └── images/
│
└── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🚀 Conclusion
&lt;/h1&gt;

&lt;p&gt;Day 4 was one of the most valuable days of the TerraWeek Challenge because it shifted my focus from simply creating infrastructure to managing it safely over time.&lt;/p&gt;

&lt;p&gt;Learning how Terraform stores infrastructure information, migrates Local State to Remote State, protects State using Native S3 Locking, and imports existing resources made me realize that Terraform is much more than an automation tool—it is a complete infrastructure management platform.&lt;/p&gt;

&lt;p&gt;Understanding State Management is essential for working on real-world DevOps projects where multiple engineers collaborate on the same infrastructure.&lt;/p&gt;

&lt;p&gt;With four days of the TerraWeek Challenge completed, I now have a much stronger understanding of both infrastructure provisioning and infrastructure management.&lt;/p&gt;

&lt;p&gt;I'm looking forward to exploring Terraform Modules and more advanced Infrastructure as Code patterns in the upcoming days.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏷️ Tags
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;#Terraform&lt;/code&gt; &lt;code&gt;#AWS&lt;/code&gt; &lt;code&gt;#TerraformState&lt;/code&gt; &lt;code&gt;#RemoteBackend&lt;/code&gt; &lt;code&gt;#AmazonS3&lt;/code&gt; &lt;code&gt;#InfrastructureAsCode&lt;/code&gt; &lt;code&gt;#DevOps&lt;/code&gt; &lt;code&gt;#CloudComputing&lt;/code&gt; &lt;code&gt;#Automation&lt;/code&gt; &lt;code&gt;#PlatformEngineering&lt;/code&gt; &lt;code&gt;#LearnInPublic&lt;/code&gt; &lt;code&gt;#TrainWithShubham&lt;/code&gt; &lt;code&gt;#TerraWeekChallenge&lt;/code&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🌱 TerraWeek Challenge – Day 3 : Providers, Resources &amp; My First Cloud Infrastructure</title>
      <dc:creator>Kshitij Sharma</dc:creator>
      <pubDate>Tue, 14 Jul 2026 07:53:25 +0000</pubDate>
      <link>https://dev.to/kshitij_sharma_fd33fdb032/terraweek-challenge-day-3-providers-resources-my-first-cloud-infrastructure-2koo</link>
      <guid>https://dev.to/kshitij_sharma_fd33fdb032/terraweek-challenge-day-3-providers-resources-my-first-cloud-infrastructure-2koo</guid>
      <description>&lt;p&gt;📅 &lt;strong&gt;Date:&lt;/strong&gt; 14 July 2026&lt;/p&gt;

&lt;p&gt;Welcome to &lt;strong&gt;Day 3&lt;/strong&gt; of my &lt;strong&gt;TerraWeek Challenge!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;p&gt;After spending the first two days understanding the fundamentals of &lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt;, Terraform, HCL, Variables, and Expressions, today was my first step into provisioning &lt;strong&gt;real cloud infrastructure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Until now, I had been working locally using providers like Docker. While those exercises helped me understand Terraform syntax and workflows, today's challenge introduced me to something much closer to real-world DevOps practices.&lt;/p&gt;

&lt;p&gt;For the first time, I learned how Terraform communicates with cloud providers, how infrastructure is created inside AWS, and how different cloud resources work together to build a complete network.&lt;/p&gt;

&lt;p&gt;The focus of today's challenge was understanding &lt;strong&gt;Providers&lt;/strong&gt;, &lt;strong&gt;Resources&lt;/strong&gt;, &lt;strong&gt;Data Sources&lt;/strong&gt;, and Terraform's powerful &lt;strong&gt;Meta-Arguments&lt;/strong&gt; such as &lt;code&gt;count&lt;/code&gt;, &lt;code&gt;for_each&lt;/code&gt;, &lt;code&gt;depends_on&lt;/code&gt;, and &lt;code&gt;lifecycle&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Along the way, I also learned the basics of AWS networking by provisioning a small infrastructure consisting of a &lt;strong&gt;VPC&lt;/strong&gt;, &lt;strong&gt;Subnet&lt;/strong&gt;, &lt;strong&gt;Internet Gateway&lt;/strong&gt;, &lt;strong&gt;Route Table&lt;/strong&gt;, &lt;strong&gt;Security Group&lt;/strong&gt;, and an &lt;strong&gt;EC2 Instance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By the end of today's session, Terraform no longer felt like just another Infrastructure as Code tool—it started feeling like a complete infrastructure automation platform.&lt;/p&gt;




&lt;h1&gt;
  
  
  📚 Learning Objectives
&lt;/h1&gt;

&lt;p&gt;By the end of Day 3, I was able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand Terraform Providers&lt;/li&gt;
&lt;li&gt;Learn why Provider Version Pinning is important&lt;/li&gt;
&lt;li&gt;Configure the AWS Provider&lt;/li&gt;
&lt;li&gt;Understand Resources and Data Sources&lt;/li&gt;
&lt;li&gt;Learn the difference between creating and reading infrastructure&lt;/li&gt;
&lt;li&gt;Understand the AWS networking fundamentals&lt;/li&gt;
&lt;li&gt;Provision cloud resources using Terraform&lt;/li&gt;
&lt;li&gt;Explore Terraform Meta-Arguments&lt;/li&gt;
&lt;li&gt;Learn how Terraform manages resource dependencies&lt;/li&gt;
&lt;li&gt;Understand Terraform Lifecycle Rules&lt;/li&gt;
&lt;li&gt;Safely provision, update, and destroy infrastructure&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  📂 Project Structure
&lt;/h1&gt;

&lt;p&gt;To keep the project organized, I separated the Terraform configuration into multiple files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── terraform.tf
├── main.tf
├── variables.tf
├── outputs.tf
├── README.md
└── images/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file has its own responsibility.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Terraform settings and AWS Provider configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;main.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Infrastructure resources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;variables.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Input variables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;outputs.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Output values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;images/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Screenshots used in the README&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Keeping the project modular improves readability and makes future maintenance much easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftnx04tz4ns2eer5t6hbj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftnx04tz4ns2eer5t6hbj.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ Prerequisites
&lt;/h1&gt;

&lt;p&gt;Before provisioning any AWS resource, I ensured the following tools were installed and configured correctly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform&lt;/li&gt;
&lt;li&gt;AWS CLI&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;li&gt;HashiCorp Terraform Extension&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike Day 2, today's challenge required communicating with AWS.&lt;/p&gt;

&lt;p&gt;Instead of storing credentials inside Terraform files, AWS CLI securely stores them in the local credentials file.&lt;/p&gt;

&lt;p&gt;This is considered one of the best security practices while working with Terraform.&lt;/p&gt;




&lt;h1&gt;
  
  
  🛠 Verifying Terraform Installation
&lt;/h1&gt;

&lt;p&gt;The first step was verifying that Terraform was installed correctly.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;This command displays the currently installed Terraform version.&lt;/p&gt;

&lt;p&gt;Verifying the installation helps ensure that the correct version is available before initializing the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw8djiujcbgkr5qb1m75t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw8djiujcbgkr5qb1m75t.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ☁️ Configuring AWS CLI
&lt;/h1&gt;

&lt;p&gt;Since Terraform needs permission to communicate with AWS, the AWS CLI must be configured before creating any infrastructure.&lt;/p&gt;

&lt;p&gt;I configured AWS credentials using:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The AWS CLI prompted me for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Access Key ID&lt;/li&gt;
&lt;li&gt;AWS Secret Access Key&lt;/li&gt;
&lt;li&gt;Default Region&lt;/li&gt;
&lt;li&gt;Output Format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform automatically uses these credentials from the local AWS credentials file.&lt;/p&gt;

&lt;p&gt;To verify everything was working correctly, I executed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws sts get-caller-identity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command confirms that Terraform will be able to authenticate with AWS successfully.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzpdw249ba90hor0veeqr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzpdw249ba90hor0veeqr.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🌍 What is a Terraform Provider?
&lt;/h1&gt;

&lt;p&gt;A &lt;strong&gt;Provider&lt;/strong&gt; is a plugin that allows Terraform to communicate with a specific platform or service.&lt;/p&gt;

&lt;p&gt;Without a provider, Terraform has no way of creating or managing infrastructure.&lt;/p&gt;

&lt;p&gt;Different providers support different platforms.&lt;/p&gt;

&lt;p&gt;Some of the most commonly used providers are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS&lt;/li&gt;
&lt;li&gt;Azure&lt;/li&gt;
&lt;li&gt;Google Cloud&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Cloudflare&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whenever Terraform executes an &lt;code&gt;apply&lt;/code&gt;, it communicates with the provider, which in turn interacts with the cloud platform using its APIs.&lt;/p&gt;

&lt;p&gt;This makes providers the bridge between Terraform and the infrastructure we want to manage.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Why Providers Matter
&lt;/h1&gt;

&lt;p&gt;Imagine writing a Terraform configuration that creates an EC2 instance.&lt;/p&gt;

&lt;p&gt;Terraform itself does not know how AWS works.&lt;/p&gt;

&lt;p&gt;Instead, it delegates the task to the &lt;strong&gt;AWS Provider&lt;/strong&gt;, which understands AWS APIs and knows how to create, update, or delete AWS resources.&lt;/p&gt;

&lt;p&gt;Similarly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Provider manages Docker resources.&lt;/li&gt;
&lt;li&gt;AzureRM Provider manages Azure resources.&lt;/li&gt;
&lt;li&gt;Google Provider manages Google Cloud resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Changing the provider often allows the same Terraform workflow to be used across different cloud platforms.&lt;/p&gt;

&lt;p&gt;This is one of the biggest reasons why Terraform is called a &lt;strong&gt;multi-cloud Infrastructure as Code tool&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  📌 Provider Version Pinning
&lt;/h1&gt;

&lt;p&gt;One of the first things I learned today was the importance of &lt;strong&gt;Version Pinning&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Terraform providers receive updates regularly.&lt;/p&gt;

&lt;p&gt;Sometimes those updates introduce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New features&lt;/li&gt;
&lt;li&gt;Bug fixes&lt;/li&gt;
&lt;li&gt;Performance improvements&lt;/li&gt;
&lt;li&gt;Breaking changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we always download the latest version automatically, an existing project may suddenly stop working after an update.&lt;/p&gt;

&lt;p&gt;To avoid this, Terraform allows us to &lt;strong&gt;pin provider versions&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;

      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 6.0"&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;The &lt;code&gt;~&amp;gt;&lt;/code&gt; operator is called the &lt;strong&gt;Pessimistic Constraint Operator&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It allows Terraform to install compatible updates while preventing unexpected major version upgrades.&lt;/p&gt;

&lt;p&gt;Version pinning makes projects stable, reproducible, and easier to maintain across teams.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌎 Provider Alias
&lt;/h1&gt;

&lt;p&gt;Terraform also supports configuring multiple instances of the same provider.&lt;/p&gt;

&lt;p&gt;This is done using &lt;strong&gt;Aliases&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ap-south-1"&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;alias&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mumbai"&lt;/span&gt;

  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ap-south-1"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Provider aliases are useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying resources across multiple AWS Regions&lt;/li&gt;
&lt;li&gt;Managing multiple AWS Accounts&lt;/li&gt;
&lt;li&gt;Creating Disaster Recovery environments&lt;/li&gt;
&lt;li&gt;Working with Multi-Region architectures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although my project used a single provider configuration, understanding aliases gave me insight into how Terraform scales for enterprise deployments.&lt;/p&gt;




&lt;h1&gt;
  
  
  📦 Resources vs Data Sources
&lt;/h1&gt;

&lt;p&gt;One of the most important concepts I learned today was the difference between &lt;strong&gt;Resources&lt;/strong&gt; and &lt;strong&gt;Data Sources&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At first, both looked very similar because both use Terraform blocks.&lt;/p&gt;

&lt;p&gt;However, their purpose is completely different.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;Resources create or manage infrastructure.&lt;/p&gt;

&lt;p&gt;Whenever Terraform creates something new, it is defined using a Resource block.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"web"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Resources are responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating infrastructure&lt;/li&gt;
&lt;li&gt;Updating infrastructure&lt;/li&gt;
&lt;li&gt;Destroying infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform keeps track of Resources inside the state file.&lt;/p&gt;




&lt;h2&gt;
  
  
  Data Sources
&lt;/h2&gt;

&lt;p&gt;Data Sources never create infrastructure.&lt;/p&gt;

&lt;p&gt;Instead, they read information that already exists.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_ami"&lt;/span&gt; &lt;span class="s2"&gt;"amazon_linux"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;most_recent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="nx"&gt;owners&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"amazon"&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;Instead of creating an AMI, Terraform simply retrieves information about the latest Amazon Linux image.&lt;/p&gt;

&lt;p&gt;Data Sources are useful for reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Existing AMIs&lt;/li&gt;
&lt;li&gt;Availability Zones&lt;/li&gt;
&lt;li&gt;Existing VPCs&lt;/li&gt;
&lt;li&gt;Existing Security Groups&lt;/li&gt;
&lt;li&gt;Existing IAM Roles&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Resources vs Data Sources
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resources&lt;/th&gt;
&lt;th&gt;Data Sources&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Create infrastructure&lt;/td&gt;
&lt;td&gt;Read existing infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Managed by Terraform&lt;/td&gt;
&lt;td&gt;Not managed by Terraform&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stored in Terraform State&lt;/td&gt;
&lt;td&gt;Only fetch information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can be updated or destroyed&lt;/td&gt;
&lt;td&gt;Read-only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Understanding this distinction is essential because most production Terraform projects use a combination of both.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏗 Understanding AWS Networking
&lt;/h1&gt;

&lt;p&gt;Before creating infrastructure, today's assignment introduced a simple overview of AWS networking.&lt;/p&gt;

&lt;p&gt;Initially, terms like &lt;strong&gt;VPC&lt;/strong&gt;, &lt;strong&gt;Subnet&lt;/strong&gt;, and &lt;strong&gt;Internet Gateway&lt;/strong&gt; sounded confusing.&lt;/p&gt;

&lt;p&gt;However, thinking of them as parts of a neighborhood made them much easier to understand.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VPC&lt;/strong&gt; → Your own private neighborhood.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subnet&lt;/strong&gt; → A street inside that neighborhood.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internet Gateway&lt;/strong&gt; → The main gate connecting your neighborhood to the internet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route Table&lt;/strong&gt; → Road signs that tell traffic where to go.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Group&lt;/strong&gt; → A security guard deciding who can enter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2 Instance&lt;/strong&gt; → The actual house where your application lives.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, these resources form the foundation of a basic AWS network.&lt;/p&gt;

&lt;p&gt;Understanding how these components connect before writing Terraform code made the implementation much easier.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ Configuring the AWS Provider
&lt;/h1&gt;

&lt;p&gt;After understanding what Providers are and why they are important, the next step was configuring the &lt;strong&gt;AWS Provider&lt;/strong&gt; inside Terraform.&lt;/p&gt;

&lt;p&gt;A provider tells Terraform which platform it should communicate with and how that communication should happen.&lt;/p&gt;

&lt;p&gt;Since today's challenge focused on AWS, I configured the &lt;strong&gt;HashiCorp AWS Provider&lt;/strong&gt; with version pinning.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 1.5.0"&lt;/span&gt;

  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;

      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 6.0"&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="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_region&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Instead of hardcoding the region directly, I used a variable to make the configuration reusable across multiple environments.&lt;/p&gt;

&lt;p&gt;This allows the same Terraform project to work with different AWS Regions by simply changing the input variable.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌎 Understanding Resources
&lt;/h1&gt;

&lt;p&gt;Resources are the heart of every Terraform project.&lt;/p&gt;

&lt;p&gt;Whenever Terraform creates something in the cloud, it is defined using a &lt;strong&gt;Resource Block&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Examples of AWS Resources include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPC&lt;/li&gt;
&lt;li&gt;Subnet&lt;/li&gt;
&lt;li&gt;Internet Gateway&lt;/li&gt;
&lt;li&gt;Route Table&lt;/li&gt;
&lt;li&gt;Security Group&lt;/li&gt;
&lt;li&gt;EC2 Instance&lt;/li&gt;
&lt;li&gt;S3 Bucket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each Resource block describes the desired state of the infrastructure.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_vpc"&lt;/span&gt; &lt;span class="s2"&gt;"main"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;cidr_block&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Here, Terraform creates a new VPC inside AWS.&lt;/p&gt;

&lt;p&gt;Once created, Terraform tracks this resource inside the &lt;strong&gt;terraform.tfstate&lt;/strong&gt; file.&lt;/p&gt;

&lt;p&gt;This state file helps Terraform understand what has already been created and what changes are required during future deployments.&lt;/p&gt;




&lt;h1&gt;
  
  
  📖 Understanding Data Sources
&lt;/h1&gt;

&lt;p&gt;Unlike Resources, &lt;strong&gt;Data Sources&lt;/strong&gt; do not create anything.&lt;/p&gt;

&lt;p&gt;Instead, they fetch information that already exists.&lt;/p&gt;

&lt;p&gt;For today's assignment, I used a Data Source to retrieve the latest Amazon Linux 2023 AMI.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_ami"&lt;/span&gt; &lt;span class="s2"&gt;"amazon_linux"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;most_recent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="nx"&gt;owners&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"amazon"&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 block searches AWS and returns the latest available Amazon Linux image.&lt;/p&gt;

&lt;p&gt;Using a Data Source is much better than hardcoding an AMI ID because AMI IDs change over time.&lt;/p&gt;

&lt;p&gt;Whenever a newer Amazon Linux image becomes available, Terraform automatically retrieves the latest one.&lt;/p&gt;

&lt;p&gt;This makes the infrastructure more reliable and future-proof.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Why Use Data Sources?
&lt;/h1&gt;

&lt;p&gt;Suppose I manually write an AMI ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ami-0abc123456789
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a few months, AWS may release a newer image.&lt;/p&gt;

&lt;p&gt;If I continue using the old AMI, my EC2 instance won't use the latest updates.&lt;/p&gt;

&lt;p&gt;Instead, using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_ami"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform always selects the latest matching image automatically.&lt;/p&gt;

&lt;p&gt;This eliminates manual maintenance.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚡ Meta-Arguments in Terraform
&lt;/h1&gt;

&lt;p&gt;Today's challenge also introduced &lt;strong&gt;Meta-Arguments&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Meta-Arguments are special arguments that modify how Terraform creates resources.&lt;/p&gt;

&lt;p&gt;Unlike normal arguments, Meta-Arguments work across many resource types.&lt;/p&gt;

&lt;p&gt;The four Meta-Arguments explored today were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;count&lt;/li&gt;
&lt;li&gt;for_each&lt;/li&gt;
&lt;li&gt;depends_on&lt;/li&gt;
&lt;li&gt;lifecycle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's understand each one.&lt;/p&gt;




&lt;h1&gt;
  
  
  1️⃣ count
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;count&lt;/code&gt; Meta-Argument creates multiple identical resources.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"web"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Instead of creating one EC2 instance, Terraform creates &lt;strong&gt;two identical instances&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is useful when all resources are exactly the same.&lt;/p&gt;

&lt;p&gt;However, if one resource is deleted later, Terraform may need to renumber the remaining resources.&lt;/p&gt;

&lt;p&gt;Because of this limitation, &lt;code&gt;count&lt;/code&gt; is best suited for identical infrastructure.&lt;/p&gt;




&lt;h1&gt;
  
  
  2️⃣ for_each
&lt;/h1&gt;

&lt;p&gt;Unlike &lt;code&gt;count&lt;/code&gt;, &lt;code&gt;for_each&lt;/code&gt; creates resources using unique keys.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_security_group"&lt;/span&gt; &lt;span class="s2"&gt;"sg"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;web&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;

    &lt;span class="nx"&gt;ssh&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&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;Each resource gets its own identity.&lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better readability&lt;/li&gt;
&lt;li&gt;Easier updates&lt;/li&gt;
&lt;li&gt;Stable resource names&lt;/li&gt;
&lt;li&gt;No index shifting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of these advantages, &lt;code&gt;for_each&lt;/code&gt; is generally preferred over &lt;code&gt;count&lt;/code&gt; whenever resources have unique names.&lt;/p&gt;




&lt;h1&gt;
  
  
  3️⃣ depends_on
&lt;/h1&gt;

&lt;p&gt;Terraform automatically detects dependencies.&lt;/p&gt;

&lt;p&gt;However, sometimes explicit dependencies are required.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"web"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;

    &lt;span class="nx"&gt;aws_internet_gateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&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 tells Terraform that the Internet Gateway must be created before the EC2 instance.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;depends_on&lt;/code&gt; avoids race conditions during deployment.&lt;/p&gt;




&lt;h1&gt;
  
  
  4️⃣ lifecycle
&lt;/h1&gt;

&lt;p&gt;Lifecycle rules control how Terraform manages resources.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;create_before_destroy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="nx"&gt;prevent_destroy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Some commonly used lifecycle rules include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create_before_destroy&lt;/li&gt;
&lt;li&gt;prevent_destroy&lt;/li&gt;
&lt;li&gt;ignore_changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lifecycle rules provide greater control over infrastructure updates.&lt;/p&gt;

&lt;p&gt;For production environments, these settings can help prevent downtime and accidental deletion of critical resources.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 Terraform Resource Dependencies
&lt;/h1&gt;

&lt;p&gt;One of the most interesting things I learned today is that Terraform automatically builds a dependency graph.&lt;/p&gt;

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

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

↓

Subnet

↓

Internet Gateway

↓

Route Table

↓

Security Group

↓

EC2 Instance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform understands these relationships automatically by reading references inside the configuration.&lt;/p&gt;

&lt;p&gt;As a result, resources are created in the correct order without requiring manual intervention.&lt;/p&gt;

&lt;p&gt;Only when Terraform cannot determine the dependency do we use &lt;code&gt;depends_on&lt;/code&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  📋 Understanding Terraform State
&lt;/h1&gt;

&lt;p&gt;Every time Terraform creates infrastructure, it records the details inside a &lt;strong&gt;State File&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The State File stores information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource IDs&lt;/li&gt;
&lt;li&gt;Current Configuration&lt;/li&gt;
&lt;li&gt;Metadata&lt;/li&gt;
&lt;li&gt;Resource Relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform compares this file with the configuration to determine what needs to be created, updated, or destroyed.&lt;/p&gt;

&lt;p&gt;Without the State File, Terraform would have no way of tracking existing infrastructure.&lt;/p&gt;




&lt;h1&gt;
  
  
  📄 Listing Managed Resources
&lt;/h1&gt;

&lt;p&gt;Terraform also provides a command to display every resource currently managed by the State File.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform state list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command lists all resources Terraform is managing.&lt;/p&gt;

&lt;p&gt;For today's project, the output included resources such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS VPC&lt;/li&gt;
&lt;li&gt;Public Subnet&lt;/li&gt;
&lt;li&gt;Internet Gateway&lt;/li&gt;
&lt;li&gt;Route Table&lt;/li&gt;
&lt;li&gt;Security Group&lt;/li&gt;
&lt;li&gt;EC2 Instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This command is extremely useful for debugging and understanding the current infrastructure.&lt;/p&gt;




&lt;h1&gt;
  
  
  💡 Best Practices Learned Today
&lt;/h1&gt;

&lt;p&gt;While working on today's assignment, I also learned a few important best practices.&lt;/p&gt;

&lt;p&gt;✔ Always pin provider versions.&lt;/p&gt;

&lt;p&gt;✔ Never hardcode AWS credentials inside Terraform files.&lt;/p&gt;

&lt;p&gt;✔ Use Data Sources instead of hardcoding AMI IDs.&lt;/p&gt;

&lt;p&gt;✔ Prefer &lt;code&gt;for_each&lt;/code&gt; over &lt;code&gt;count&lt;/code&gt; whenever resources have unique identities.&lt;/p&gt;

&lt;p&gt;✔ Use Lifecycle rules carefully to avoid accidental resource deletion.&lt;/p&gt;

&lt;p&gt;✔ Let Terraform manage dependencies automatically whenever possible.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Provisioning My First Cloud Infrastructure
&lt;/h1&gt;

&lt;p&gt;After understanding Providers, Resources, Data Sources, and Meta-Arguments, it was finally time to deploy my first real cloud infrastructure using Terraform.&lt;/p&gt;

&lt;p&gt;Unlike the previous days where I worked with local resources, today's challenge focused on provisioning infrastructure inside AWS. This helped me understand how Terraform interacts with cloud providers and automates the creation of networking and compute resources.&lt;/p&gt;

&lt;p&gt;The infrastructure created during this challenge included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Virtual Private Cloud (VPC)&lt;/li&gt;
&lt;li&gt;Public Subnet&lt;/li&gt;
&lt;li&gt;Internet Gateway&lt;/li&gt;
&lt;li&gt;Route Table&lt;/li&gt;
&lt;li&gt;Route Table Association&lt;/li&gt;
&lt;li&gt;Security Group&lt;/li&gt;
&lt;li&gt;EC2 Instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each resource had its own responsibility, but Terraform managed all of them together as a single Infrastructure as Code project.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 Terraform Workflow
&lt;/h1&gt;

&lt;p&gt;Before creating any infrastructure, I followed Terraform's standard workflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write Configuration

        ↓

terraform init

        ↓

terraform validate

        ↓

terraform plan

        ↓

terraform apply

        ↓

terraform output

        ↓

terraform state list

        ↓

terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow helps verify the configuration before deployment and ensures infrastructure changes remain predictable.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Step 1 — Initialize Terraform
&lt;/h1&gt;

&lt;p&gt;The first command executed in every Terraform project is:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This command initializes the working directory and downloads all required provider plugins.&lt;/p&gt;

&lt;p&gt;During initialization Terraform also creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.terraform/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.terraform.lock.hcl&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the initialization completes successfully, Terraform confirms that the project is ready for execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvk8r6uphu2iq9fc065n6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvk8r6uphu2iq9fc065n6.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ✅ Step 2 — Validate the Configuration
&lt;/h1&gt;

&lt;p&gt;Before provisioning infrastructure, I validated the Terraform configuration.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform checked the configuration for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syntax errors&lt;/li&gt;
&lt;li&gt;Missing references&lt;/li&gt;
&lt;li&gt;Invalid arguments&lt;/li&gt;
&lt;li&gt;Unsupported attributes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything is correct, Terraform displays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Success! The configuration is valid.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running validation before deployment is a good habit because it catches mistakes early.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frjnw4q39qj6j3sa94ote.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frjnw4q39qj6j3sa94ote.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📋 Step 3 — Review the Execution Plan
&lt;/h1&gt;

&lt;p&gt;Next, I generated an execution plan.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform compared the desired configuration with the current infrastructure and displayed every action it planned to perform.&lt;/p&gt;

&lt;p&gt;The plan included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a VPC&lt;/li&gt;
&lt;li&gt;Creating a Public Subnet&lt;/li&gt;
&lt;li&gt;Attaching an Internet Gateway&lt;/li&gt;
&lt;li&gt;Creating a Route Table&lt;/li&gt;
&lt;li&gt;Creating a Security Group&lt;/li&gt;
&lt;li&gt;Launching an EC2 Instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end of the execution plan Terraform displayed a summary similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan: 6 to add, 0 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The planning phase provides an opportunity to review infrastructure changes before they are applied.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz5j0d13htdcjk44qqa63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz5j0d13htdcjk44qqa63.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Step 4 — Apply the Configuration
&lt;/h1&gt;

&lt;p&gt;After reviewing the execution plan, I deployed the infrastructure.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform asked for confirmation before creating the resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you want to perform these actions?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After entering:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform began provisioning the AWS infrastructure.&lt;/p&gt;

&lt;p&gt;The deployment included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating the VPC&lt;/li&gt;
&lt;li&gt;Creating the Public Subnet&lt;/li&gt;
&lt;li&gt;Creating the Internet Gateway&lt;/li&gt;
&lt;li&gt;Configuring the Route Table&lt;/li&gt;
&lt;li&gt;Creating the Security Group&lt;/li&gt;
&lt;li&gt;Launching the EC2 Instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After a few moments, Terraform displayed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apply complete!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watching an entire cloud environment being created from a few Terraform files was one of the biggest highlights of today's challenge.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo8rgldt6j5jzvipxqyey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo8rgldt6j5jzvipxqyey.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ☁️ Verifying Resources in AWS
&lt;/h1&gt;

&lt;p&gt;Once Terraform finished creating the infrastructure, I logged into the AWS Management Console to verify that every resource had been created successfully.&lt;/p&gt;

&lt;p&gt;I confirmed the following resources were available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPC&lt;/li&gt;
&lt;li&gt;Public Subnet&lt;/li&gt;
&lt;li&gt;Internet Gateway&lt;/li&gt;
&lt;li&gt;Route Table&lt;/li&gt;
&lt;li&gt;Security Group&lt;/li&gt;
&lt;li&gt;EC2 Instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verifying the deployment in AWS helped me connect the Terraform configuration with the actual cloud resources.&lt;/p&gt;




&lt;h1&gt;
  
  
  📤 Viewing Terraform Outputs
&lt;/h1&gt;

&lt;p&gt;Terraform Outputs display useful information after the infrastructure has been created.&lt;/p&gt;

&lt;p&gt;Instead of manually searching for resource IDs or IP addresses, Terraform automatically displays them.&lt;/p&gt;

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

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;instance_id = "i-xxxxxxxx"

public_ip = "xx.xx.xx.xx"

vpc_id = "vpc-xxxxxxxx"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outputs make Terraform configurations much easier to consume and can also be used by other modules or CI/CD pipelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx8ljqwkh27dexwdyf2bi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx8ljqwkh27dexwdyf2bi.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📦 Understanding Terraform State
&lt;/h1&gt;

&lt;p&gt;One of the most important concepts I learned today was the &lt;strong&gt;Terraform State File&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Whenever Terraform creates infrastructure, it stores information inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The state file contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource IDs&lt;/li&gt;
&lt;li&gt;Current infrastructure&lt;/li&gt;
&lt;li&gt;Metadata&lt;/li&gt;
&lt;li&gt;Dependency information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform uses this file to compare the existing infrastructure with the desired configuration and determine what changes are required.&lt;/p&gt;

&lt;p&gt;Without the state file, Terraform would not know which resources it already manages.&lt;/p&gt;




&lt;h1&gt;
  
  
  📄 Listing Managed Resources
&lt;/h1&gt;

&lt;p&gt;Terraform also provides a command to display every resource currently tracked inside the state file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform state list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output included resources such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;aws_vpc.main&lt;/li&gt;
&lt;li&gt;aws_subnet.public&lt;/li&gt;
&lt;li&gt;aws_internet_gateway.main&lt;/li&gt;
&lt;li&gt;aws_route_table.public&lt;/li&gt;
&lt;li&gt;aws_security_group.web&lt;/li&gt;
&lt;li&gt;aws_instance.web&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This command is extremely useful for debugging and understanding the current infrastructure managed by Terraform.&lt;/p&gt;




&lt;h1&gt;
  
  
  🍫 Bonus Exploration
&lt;/h1&gt;

&lt;p&gt;After completing the core tasks, I explored some additional Terraform features that are commonly used in real-world Infrastructure as Code projects.&lt;/p&gt;

&lt;p&gt;Although these features are considered bonus tasks for today's challenge, they helped me understand how Terraform can automate deployments even further and simplify infrastructure management.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 1 — Automating Server Setup using User Data
&lt;/h1&gt;

&lt;p&gt;One of the bonus tasks suggested either attaching an Elastic IP or using &lt;strong&gt;User Data&lt;/strong&gt; to automatically install Nginx during the EC2 instance launch.&lt;/p&gt;

&lt;p&gt;For this project, I chose the &lt;strong&gt;User Data&lt;/strong&gt; approach because it demonstrates Infrastructure as Code more effectively.&lt;/p&gt;

&lt;p&gt;Instead of manually connecting to the EC2 instance and installing software, Terraform executes a shell script automatically when the instance boots for the first time.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;user_data&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
#!/bin/bash
yum update -y
yum install -y nginx
systemctl enable nginx
systemctl start nginx
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script performs the following actions automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updates the package repository.&lt;/li&gt;
&lt;li&gt;Installs the Nginx web server.&lt;/li&gt;
&lt;li&gt;Enables the Nginx service.&lt;/li&gt;
&lt;li&gt;Starts the web server immediately after launch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using &lt;strong&gt;User Data&lt;/strong&gt; eliminates manual configuration and ensures every EC2 instance is configured consistently.&lt;/p&gt;

&lt;p&gt;This is one of the key advantages of Infrastructure as Code.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 2 — Visualizing Resource Dependencies
&lt;/h1&gt;

&lt;p&gt;Terraform automatically understands the relationships between resources.&lt;/p&gt;

&lt;p&gt;To visualize these dependencies, Terraform provides the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform graph &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; graph.dot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates a &lt;strong&gt;DOT&lt;/strong&gt; file containing the dependency graph.&lt;/p&gt;

&lt;p&gt;Using &lt;strong&gt;Graphviz&lt;/strong&gt;, the DOT file can be converted into an image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dot &lt;span class="nt"&gt;-Tpng&lt;/span&gt; graph.dot &lt;span class="nt"&gt;-o&lt;/span&gt; graph.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated graph clearly illustrates how Terraform determines the order in which resources should be created.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VPC
   │
   ▼
Subnet
   │
   ▼
Internet Gateway
   │
   ▼
Route Table
   │
   ▼
Security Group
   │
   ▼
EC2 Instance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Understanding this dependency graph helped me appreciate how Terraform automatically manages resource creation without requiring manual sequencing.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fju3vrxy6y8la70ti605a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fju3vrxy6y8la70ti605a.png" alt=" " width="800" height="157"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Bonus 3 — Understanding the &lt;code&gt;moved&lt;/code&gt; Block
&lt;/h1&gt;

&lt;p&gt;Terraform also provides the &lt;strong&gt;moved block&lt;/strong&gt;, which allows developers to rename resources without destroying and recreating them.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;moved&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web&lt;/span&gt;

  &lt;span class="nx"&gt;to&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Normally, renaming a resource would cause Terraform to destroy the existing resource and create a new one.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;moved&lt;/code&gt; block updates Terraform's state instead, preserving the existing infrastructure while reflecting the new resource name in the configuration.&lt;/p&gt;

&lt;p&gt;Although I didn't need to rename any resources in this project, learning about the &lt;code&gt;moved&lt;/code&gt; block gave me a better understanding of how Terraform safely handles refactoring.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧹 Destroying Infrastructure
&lt;/h1&gt;

&lt;p&gt;Once I verified that everything was working correctly, I removed all the resources created during this challenge.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Terraform displayed a confirmation prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you really want to destroy all resources?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After entering:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform destroyed every managed resource in the correct dependency order.&lt;/p&gt;

&lt;p&gt;This included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPC&lt;/li&gt;
&lt;li&gt;Public Subnet&lt;/li&gt;
&lt;li&gt;Internet Gateway&lt;/li&gt;
&lt;li&gt;Route Table&lt;/li&gt;
&lt;li&gt;Security Group&lt;/li&gt;
&lt;li&gt;EC2 Instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, Terraform displayed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destroy complete!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Destroying unused cloud resources is an important best practice because it helps avoid unnecessary AWS charges and keeps the environment clean.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fin1tjdto7vn6dg4ppiu3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fin1tjdto7vn6dg4ppiu3.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 What I Learned
&lt;/h1&gt;

&lt;p&gt;Day 3 was my first experience provisioning real cloud infrastructure using Terraform, and it significantly expanded my understanding of Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;Some of the key takeaways from today's challenge are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learned how Terraform communicates with AWS using Providers.&lt;/li&gt;
&lt;li&gt;Understood the importance of Provider Version Pinning.&lt;/li&gt;
&lt;li&gt;Explored the difference between Resources and Data Sources.&lt;/li&gt;
&lt;li&gt;Learned the basics of AWS Networking, including VPCs, Subnets, Internet Gateways, Route Tables, Security Groups, and EC2.&lt;/li&gt;
&lt;li&gt;Used Data Sources to retrieve existing AWS information dynamically.&lt;/li&gt;
&lt;li&gt;Explored Terraform Meta-Arguments such as &lt;code&gt;count&lt;/code&gt;, &lt;code&gt;for_each&lt;/code&gt;, &lt;code&gt;depends_on&lt;/code&gt;, and &lt;code&gt;lifecycle&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Learned how Terraform automatically manages resource dependencies.&lt;/li&gt;
&lt;li&gt;Understood the role of the Terraform State File.&lt;/li&gt;
&lt;li&gt;Explored bonus concepts such as User Data, Terraform Graph, and the Moved Block.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest lesson from today was that Infrastructure as Code isn't just about provisioning cloud resources—it's about creating infrastructure that is automated, reusable, version-controlled, and easy to maintain.&lt;/p&gt;




&lt;h1&gt;
  
  
  📂 Repository Structure
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TerraWeek/
│
├── Day-01/
│   ├── README.md
│   ├── example/
│   └── images/
│
├── Day-02/
│   ├── README.md
│   ├── example/
│   └── images/
│
├── Day-03/
│   ├── terraform.tf
│   ├── main.tf
│   ├── variables.tf
│   ├── outputs.tf
│   ├── README.md
│   └── images/
│
└── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🚀 Conclusion
&lt;/h1&gt;

&lt;p&gt;Day 3 was an exciting milestone in my Terraform journey because it introduced me to real cloud infrastructure.&lt;/p&gt;

&lt;p&gt;The previous two days helped me understand Terraform syntax and HCL, but today's challenge showed me how those concepts come together to provision an actual AWS environment.&lt;/p&gt;

&lt;p&gt;From configuring Providers and using Data Sources to deploying an EC2 instance inside a custom VPC, every step reinforced the power of Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;I also explored advanced Terraform capabilities such as Meta-Arguments, User Data, Terraform Graph, and the Moved Block, which are commonly used in production environments.&lt;/p&gt;

&lt;p&gt;With three days of the TerraWeek Challenge completed, I now have a much stronger understanding of how Terraform can automate cloud infrastructure in a consistent, repeatable, and scalable way.&lt;/p&gt;

&lt;p&gt;I'm excited to continue the journey and explore even more advanced Terraform concepts in the upcoming days.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏷️ Tags
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;#Terraform&lt;/code&gt; &lt;code&gt;#AWS&lt;/code&gt; &lt;code&gt;#InfrastructureAsCode&lt;/code&gt; &lt;code&gt;#CloudComputing&lt;/code&gt; &lt;code&gt;#DevOps&lt;/code&gt; &lt;code&gt;#HashiCorp&lt;/code&gt; &lt;code&gt;#EC2&lt;/code&gt; &lt;code&gt;#VPC&lt;/code&gt; &lt;code&gt;#Automation&lt;/code&gt; &lt;code&gt;#CloudEngineer&lt;/code&gt; &lt;code&gt;#LearnInPublic&lt;/code&gt; &lt;code&gt;#TrainWithShubham&lt;/code&gt; &lt;code&gt;#TerraWeekChallenge&lt;/code&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🌱 TerraWeek Challenge – Day 2 - HCL Deep Dive: Variables, Types &amp; Expressions</title>
      <dc:creator>Kshitij Sharma</dc:creator>
      <pubDate>Mon, 13 Jul 2026 12:24:01 +0000</pubDate>
      <link>https://dev.to/kshitij_sharma_fd33fdb032/terraweek-challenge-day-2-hcl-deep-dive-variables-types-expressions-4fa4</link>
      <guid>https://dev.to/kshitij_sharma_fd33fdb032/terraweek-challenge-day-2-hcl-deep-dive-variables-types-expressions-4fa4</guid>
      <description>&lt;p&gt;📅 &lt;strong&gt;Date:&lt;/strong&gt; 13 July 2026&lt;/p&gt;

&lt;p&gt;Welcome to &lt;strong&gt;Day 2&lt;/strong&gt; of my &lt;strong&gt;TerraWeek Challenge!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;p&gt;After completing Day 1, where I learned the fundamentals of &lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt; and deployed my very first infrastructure using Terraform, today's challenge focused on understanding the language behind Terraform itself—&lt;strong&gt;HashiCorp Configuration Language (HCL)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On Day 1, I learned how Terraform works.&lt;/p&gt;

&lt;p&gt;On Day 2, I explored &lt;strong&gt;how Terraform configurations are actually written&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of using fixed values inside Terraform files, I learned how to create reusable and dynamic configurations using &lt;strong&gt;Variables&lt;/strong&gt;, &lt;strong&gt;Expressions&lt;/strong&gt;, &lt;strong&gt;Locals&lt;/strong&gt;, &lt;strong&gt;Outputs&lt;/strong&gt;, and several &lt;strong&gt;built-in Terraform Functions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To put these concepts into practice, I deployed an &lt;strong&gt;Nginx Docker container&lt;/strong&gt; using the Docker Provider, where almost every configurable value was controlled through variables instead of being hardcoded.&lt;/p&gt;

&lt;p&gt;By the end of today's challenge, I gained a much deeper understanding of how professional Terraform configurations are structured and why HCL plays such an important role in Infrastructure as Code.&lt;/p&gt;




&lt;h1&gt;
  
  
  📚 Learning Objectives
&lt;/h1&gt;

&lt;p&gt;By the end of Day 2, I was able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand HashiCorp Configuration Language (HCL)&lt;/li&gt;
&lt;li&gt;Learn the structure of Terraform configuration files&lt;/li&gt;
&lt;li&gt;Differentiate between Blocks and Arguments&lt;/li&gt;
&lt;li&gt;Work with HCL Expressions&lt;/li&gt;
&lt;li&gt;Create reusable configurations using Variables&lt;/li&gt;
&lt;li&gt;Explore all major Terraform Variable Types&lt;/li&gt;
&lt;li&gt;Apply Variable Validation&lt;/li&gt;
&lt;li&gt;Protect confidential information using Sensitive Variables&lt;/li&gt;
&lt;li&gt;Use Locals for reusable values&lt;/li&gt;
&lt;li&gt;Generate useful Outputs&lt;/li&gt;
&lt;li&gt;Explore commonly used Terraform Functions&lt;/li&gt;
&lt;li&gt;Understand Variable Precedence&lt;/li&gt;
&lt;li&gt;Deploy an Nginx Docker container using Terraform&lt;/li&gt;
&lt;li&gt;Explore advanced HCL concepts such as For Expressions and Conditional Expressions&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  📂 Project Structure
&lt;/h1&gt;

&lt;p&gt;Before starting the implementation, I organized my Terraform project into multiple files. Instead of writing everything inside a single file, each file was given a specific responsibility, making the project much cleaner and easier to maintain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── terraform.tf
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars
├── README.md
└── images/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file serves a different purpose:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Configures the Terraform and Docker provider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;main.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Defines Docker resources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;variables.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Declares input variables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform.tfvars&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stores variable values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;outputs.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Displays useful information after deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Project documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Organizing Terraform projects in this way improves readability and makes the codebase easier to manage as projects grow.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz929spmyhgj68hyfgtxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz929spmyhgj68hyfgtxp.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ Prerequisites
&lt;/h1&gt;

&lt;p&gt;Before working on today's challenge, I made sure that the following tools were installed and configured correctly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform&lt;/li&gt;
&lt;li&gt;Docker Desktop&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;li&gt;HashiCorp Terraform Extension&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since today's project uses the &lt;strong&gt;Docker Provider&lt;/strong&gt;, Docker Desktop must be running before executing any Terraform commands.&lt;/p&gt;




&lt;h1&gt;
  
  
  🛠 Verifying Terraform Installation
&lt;/h1&gt;

&lt;p&gt;The first step was to verify whether Terraform was installed correctly.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;This command displays the currently installed version of Terraform along with additional build information.&lt;/p&gt;

&lt;p&gt;Verifying the installation beforehand helps avoid unnecessary troubleshooting later in the workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqarby5ay8wndg7f97kmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqarby5ay8wndg7f97kmn.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🐳 Verifying Docker Installation
&lt;/h1&gt;

&lt;p&gt;Since the project deploys an Nginx container locally, Docker must also be installed and running.&lt;/p&gt;

&lt;p&gt;I verified Docker by executing the following command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Alternatively, the following command can also be used:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If Docker is running correctly, it displays the client and server information (or the list of running containers).&lt;/p&gt;

&lt;p&gt;Ensuring Docker is running before initializing Terraform prevents provider connection errors during deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9zz3gqn35v641sks3lxk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9zz3gqn35v641sks3lxk.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📖 What is HCL?
&lt;/h1&gt;

&lt;p&gt;HCL stands for &lt;strong&gt;HashiCorp Configuration Language&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is a declarative language developed by HashiCorp specifically for writing Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;Unlike traditional programming languages where developers describe every individual step, HCL focuses on defining the &lt;strong&gt;desired state&lt;/strong&gt; of the infrastructure.&lt;/p&gt;

&lt;p&gt;Terraform reads the configuration, compares it with the current state, and automatically determines what changes are required to reach the desired state.&lt;/p&gt;

&lt;p&gt;Because of this declarative approach, HCL configurations remain simple, readable, and easy to maintain.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌍 Why Do We Need HCL?
&lt;/h1&gt;

&lt;p&gt;Imagine deploying the same infrastructure for multiple environments such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Development&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Staging&lt;/li&gt;
&lt;li&gt;Production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If every configuration contained hardcoded values, we would have to edit the Terraform files before every deployment.&lt;/p&gt;

&lt;p&gt;This approach quickly becomes difficult to manage.&lt;/p&gt;

&lt;p&gt;HCL solves this problem by allowing configurations to become:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reusable&lt;/li&gt;
&lt;li&gt;Readable&lt;/li&gt;
&lt;li&gt;Consistent&lt;/li&gt;
&lt;li&gt;Scalable&lt;/li&gt;
&lt;li&gt;Easy to Maintain&lt;/li&gt;
&lt;li&gt;Version Controlled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of changing the infrastructure code repeatedly, we simply provide different variable values and Terraform takes care of the rest.&lt;/p&gt;

&lt;p&gt;This is one of the primary reasons why Terraform is widely adopted across the industry.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏗 Understanding the Anatomy of an HCL Block
&lt;/h1&gt;

&lt;p&gt;Every Terraform configuration is built using &lt;strong&gt;Blocks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A block represents a specific component of the configuration, such as a provider, resource, variable, output, or module.&lt;/p&gt;

&lt;p&gt;The basic syntax of an HCL block looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;block_type&lt;/span&gt; &lt;span class="s2"&gt;"label_one"&lt;/span&gt; &lt;span class="s2"&gt;"label_two"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;argument&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Each part of the block has its own purpose.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Block Type&lt;/td&gt;
&lt;td&gt;Specifies the kind of block&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Label One&lt;/td&gt;
&lt;td&gt;Resource or Provider Type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Label Two&lt;/td&gt;
&lt;td&gt;Local Name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arguments&lt;/td&gt;
&lt;td&gt;Configuration values&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"docker_container"&lt;/span&gt; &lt;span class="s2"&gt;"web"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_name&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;resource&lt;/code&gt; is the block type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker_container&lt;/code&gt; specifies the type of resource.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;web&lt;/code&gt; is the local name.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; is an argument that receives its value from a variable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding this structure is essential because almost every Terraform configuration follows this pattern.&lt;/p&gt;




&lt;h1&gt;
  
  
  📦 Understanding Blocks
&lt;/h1&gt;

&lt;p&gt;Terraform provides different block types, each designed for a specific purpose.&lt;/p&gt;

&lt;p&gt;Some commonly used blocks include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;terraform&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;provider&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;variable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;locals&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;output&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;module&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, the Provider block tells Terraform which platform it should communicate with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"docker"&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;Similarly, a Resource block describes the infrastructure Terraform should create.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"docker_image"&lt;/span&gt; &lt;span class="s2"&gt;"nginx"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nginx:latest"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;A Variable block defines user input that can be reused throughout the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"container_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Although these blocks perform different tasks, they all follow the same HCL syntax.&lt;/p&gt;




&lt;h1&gt;
  
  
  📝 Arguments vs Blocks
&lt;/h1&gt;

&lt;p&gt;One concept that initially confused me was the difference between &lt;strong&gt;Arguments&lt;/strong&gt; and &lt;strong&gt;Blocks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;After experimenting with Terraform configurations, the distinction became much clearer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arguments
&lt;/h2&gt;

&lt;p&gt;Arguments assign values to configuration settings.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nginx"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;image&lt;/span&gt;    &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nginx:latest"&lt;/span&gt;
&lt;span class="nx"&gt;internal&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="nx"&gt;external&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arguments always follow the format:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Blocks
&lt;/h2&gt;

&lt;p&gt;Blocks, on the other hand, group related configuration together.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;ports&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;internal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
  &lt;span class="nx"&gt;external&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;ports&lt;/code&gt; is a nested block that contains multiple arguments.&lt;/p&gt;

&lt;p&gt;This structure keeps Terraform configurations organized and improves readability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Arguments vs Blocks
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Arguments&lt;/th&gt;
&lt;th&gt;Blocks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Assign values&lt;/td&gt;
&lt;td&gt;Group related configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Written as &lt;code&gt;key = value&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Written using &lt;code&gt;{ }&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cannot contain nested configuration&lt;/td&gt;
&lt;td&gt;Can contain arguments and nested blocks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Understanding this difference makes it much easier to read and write Terraform configurations.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔗 Understanding HCL Expressions
&lt;/h1&gt;

&lt;p&gt;Expressions allow Terraform configurations to become dynamic.&lt;/p&gt;

&lt;p&gt;Instead of hardcoding values, Terraform can calculate values during execution.&lt;/p&gt;

&lt;p&gt;Expressions can reference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Variables&lt;/li&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;li&gt;Outputs&lt;/li&gt;
&lt;li&gt;Functions&lt;/li&gt;
&lt;li&gt;Operators&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This expression retrieves the value stored inside the &lt;code&gt;environment&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Expressions can also reference resource attributes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;docker_container&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform automatically reads the name attribute of the Docker container.&lt;/p&gt;

&lt;p&gt;Another useful feature is &lt;strong&gt;String Interpolation&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="s2"&gt;"${var.environment}-container"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the value of &lt;code&gt;environment&lt;/code&gt; is:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform automatically produces:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Expressions are one of the most powerful features of HCL because they allow infrastructure to adapt based on input values instead of relying on hardcoded configurations.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔤 Understanding Terraform Variables
&lt;/h1&gt;

&lt;p&gt;After learning the basics of HCL, the next step was understanding one of the most powerful features of Terraform—&lt;strong&gt;Variables&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When I first started writing Terraform configurations, I noticed that many values such as the container name, ports, environment, and image name were hardcoded inside the resource block.&lt;/p&gt;

&lt;p&gt;Although this approach works for small projects, it quickly becomes difficult to manage when the same infrastructure needs to be deployed multiple times.&lt;/p&gt;

&lt;p&gt;For example, suppose I want to deploy the same Docker container for different environments.&lt;/p&gt;

&lt;p&gt;Development might use:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Staging could use:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Production might use:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If every value is hardcoded, I would need to edit my Terraform configuration before every deployment.&lt;/p&gt;

&lt;p&gt;Terraform Variables solve this problem.&lt;/p&gt;

&lt;p&gt;Instead of changing the code, I only change the input values, and Terraform automatically provisions the required infrastructure.&lt;/p&gt;

&lt;p&gt;This makes Terraform configurations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reusable&lt;/li&gt;
&lt;li&gt;Flexible&lt;/li&gt;
&lt;li&gt;Easier to Maintain&lt;/li&gt;
&lt;li&gt;Environment Independent&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  📦 Creating Variables
&lt;/h1&gt;

&lt;p&gt;Variables are declared using the &lt;strong&gt;variable block&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A simple variable looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"container_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Name of Docker Container"&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Each variable usually contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name&lt;/li&gt;
&lt;li&gt;Description&lt;/li&gt;
&lt;li&gt;Type&lt;/li&gt;
&lt;li&gt;Default Value (Optional)&lt;/li&gt;
&lt;li&gt;Validation (Optional)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once declared, variables can be used anywhere inside the project.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"docker_container"&lt;/span&gt; &lt;span class="s2"&gt;"web"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container_name&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Here, Terraform replaces the variable with the value provided during execution.&lt;/p&gt;




&lt;h1&gt;
  
  
  📘 Understanding Variable Types
&lt;/h1&gt;

&lt;p&gt;Terraform supports multiple variable types depending on the kind of data we want to store.&lt;/p&gt;

&lt;p&gt;For this assignment, I explored all the major variable types available in Terraform.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔹 String
&lt;/h1&gt;

&lt;p&gt;A &lt;strong&gt;String&lt;/strong&gt; stores textual values.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"container_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Possible values:&lt;br&gt;
&lt;/p&gt;

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

terraweek-web

docker-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;String variables are commonly used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names&lt;/li&gt;
&lt;li&gt;Regions&lt;/li&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;li&gt;Environment Names&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🔹 Number
&lt;/h1&gt;

&lt;p&gt;Number variables store numeric values.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"external_port"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Possible values:&lt;br&gt;
&lt;/p&gt;

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

443

8080

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

&lt;/div&gt;



&lt;p&gt;Terraform automatically understands these values as numbers instead of text.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔹 Boolean
&lt;/h1&gt;

&lt;p&gt;Boolean variables contain only two values.&lt;br&gt;
&lt;/p&gt;

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

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"enable_logging"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bool&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;These are commonly used to enable or disable optional features.&lt;/p&gt;




&lt;h1&gt;
  
  
  📚 Collection Types
&lt;/h1&gt;

&lt;p&gt;Collection Types store multiple values together.&lt;/p&gt;

&lt;p&gt;Terraform provides several collection types.&lt;/p&gt;




&lt;h2&gt;
  
  
  List
&lt;/h2&gt;

&lt;p&gt;A List stores ordered values.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"ports"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&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;Example value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;8080&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lists preserve the order of values.&lt;/p&gt;




&lt;h2&gt;
  
  
  Map
&lt;/h2&gt;

&lt;p&gt;Maps store values as &lt;strong&gt;Key → Value&lt;/strong&gt; pairs.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"extra_labels"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&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;Value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="nx"&gt;project&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraweek"&lt;/span&gt;

&lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"aditya"&lt;/span&gt;

&lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Maps are commonly used for metadata and labels.&lt;/p&gt;




&lt;h2&gt;
  
  
  Set
&lt;/h2&gt;

&lt;p&gt;A Set is similar to a List but removes duplicate values automatically.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"allowed_ports"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&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;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;8080&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform internally converts this into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;80
443
8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps avoid duplicate entries.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧱 Structural Types
&lt;/h1&gt;

&lt;p&gt;Terraform also supports more advanced data structures.&lt;/p&gt;




&lt;h2&gt;
  
  
  Object
&lt;/h2&gt;

&lt;p&gt;Objects group multiple related values together.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"container_config"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;

    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

    &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;number&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;Example Value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nginx"&lt;/span&gt;

&lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Objects make configurations cleaner by grouping related properties.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tuple
&lt;/h2&gt;

&lt;p&gt;A Tuple stores multiple values with predefined data types.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"sample_tuple"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;

    &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="nx"&gt;bool&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;Example Value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
"nginx",
8080,
true
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike Lists, each position inside a Tuple has its own type.&lt;/p&gt;




&lt;h1&gt;
  
  
  ✅ Variable Validation
&lt;/h1&gt;

&lt;p&gt;Terraform allows us to validate user input before infrastructure is created.&lt;/p&gt;

&lt;p&gt;This helps prevent accidental configuration mistakes.&lt;/p&gt;

&lt;p&gt;For this assignment, I restricted the environment variable so that only three values are accepted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"environment"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;

  &lt;span class="nx"&gt;validation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;

      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"staging"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"prod"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

      &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;

    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;error_message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Environment must be dev, staging or prod."&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;Now, if someone provides:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply &lt;span class="nt"&gt;-var&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"environment=test"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform immediately throws an error instead of creating invalid infrastructure.&lt;/p&gt;

&lt;p&gt;Validation makes configurations much safer and more reliable.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔒 Sensitive Variables
&lt;/h1&gt;

&lt;p&gt;Sometimes Terraform configurations contain confidential information like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passwords&lt;/li&gt;
&lt;li&gt;API Keys&lt;/li&gt;
&lt;li&gt;Tokens&lt;/li&gt;
&lt;li&gt;Secrets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Displaying these values in logs or outputs would be a security risk.&lt;/p&gt;

&lt;p&gt;Terraform provides the &lt;strong&gt;Sensitive Variable&lt;/strong&gt; feature to protect confidential information.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"docker_password"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

  &lt;span class="nx"&gt;sensitive&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Whenever Terraform displays outputs, sensitive values are automatically hidden.&lt;/p&gt;

&lt;p&gt;This prevents accidental exposure of credentials.&lt;/p&gt;




&lt;h1&gt;
  
  
  📍 Understanding Locals
&lt;/h1&gt;

&lt;p&gt;Locals are reusable values calculated inside Terraform.&lt;/p&gt;

&lt;p&gt;Instead of writing the same expression multiple times, we define it once inside a &lt;code&gt;locals&lt;/code&gt; block.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;name_prefix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tws-${var.environment}"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now the same value can be reused anywhere.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name_prefix&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using Locals improves readability and reduces duplicate code.&lt;/p&gt;




&lt;h1&gt;
  
  
  🛠 Terraform Built-in Functions
&lt;/h1&gt;

&lt;p&gt;Terraform provides many built-in functions for working with strings, collections, and numbers.&lt;/p&gt;

&lt;p&gt;During this challenge, I explored some of the most commonly used functions.&lt;/p&gt;




&lt;h2&gt;
  
  
  upper()
&lt;/h2&gt;

&lt;p&gt;Converts text into uppercase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;upper&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"terraweek"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  merge()
&lt;/h2&gt;

&lt;p&gt;Combines multiple maps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;merge&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"terraweek"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extra_labels&lt;/span&gt;
&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  join()
&lt;/h2&gt;

&lt;p&gt;Joins multiple strings using a separator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"terra"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"week"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"2026"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terra-week-2026
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  format()
&lt;/h2&gt;

&lt;p&gt;Formats text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;
&lt;span class="s2"&gt;"http://localhost:%d"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;external_port&lt;/span&gt;
&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These functions make Terraform configurations much more dynamic and reusable.&lt;/p&gt;




&lt;h1&gt;
  
  
  💻 Exploring Terraform Console
&lt;/h1&gt;

&lt;p&gt;Terraform Console is an interactive shell used to evaluate HCL expressions and test Terraform functions without modifying configuration files.&lt;/p&gt;

&lt;p&gt;To start the console:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;I tested several expressions during this challenge.&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="o"&gt;&amp;gt;&lt;/span&gt; upper&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"terraweek"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"TERRAWEEK"&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; merge&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 1
  &lt;span class="s2"&gt;"b"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 2
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-"&lt;/span&gt;,[&lt;span class="s2"&gt;"terra"&lt;/span&gt;,&lt;span class="s2"&gt;"week"&lt;/span&gt;,&lt;span class="s2"&gt;"2026"&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
&lt;span class="s2"&gt;"terra-week-2026"&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; length&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"docker"&lt;/span&gt;,&lt;span class="s2"&gt;"terraform"&lt;/span&gt;,&lt;span class="s2"&gt;"hcl"&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the console helped me understand how functions and expressions behave before using them in actual Terraform code.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Finvsjma9birffewygid5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Finvsjma9birffewygid5.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Building a Real Terraform Project
&lt;/h1&gt;

&lt;p&gt;After learning HCL, Variables, Locals, Functions, and Expressions, it was finally time to implement everything in a real Terraform project.&lt;/p&gt;

&lt;p&gt;Instead of provisioning cloud resources on AWS or Azure, today's assignment uses the &lt;strong&gt;Docker Provider&lt;/strong&gt; to deploy an &lt;strong&gt;Nginx container&lt;/strong&gt; locally.&lt;/p&gt;

&lt;p&gt;The advantage of using Docker is that we can practice all Terraform concepts without creating a cloud account or worrying about cloud costs.&lt;/p&gt;

&lt;p&gt;Although the provider changes, the Terraform workflow remains exactly the same.&lt;/p&gt;

&lt;p&gt;Whether Terraform creates an EC2 instance on AWS or an Nginx container using Docker, the configuration syntax and workflow remain identical.&lt;/p&gt;

&lt;p&gt;Today's implementation helped me understand how Terraform combines HCL with providers to automate infrastructure deployment.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔄 Terraform Workflow
&lt;/h1&gt;

&lt;p&gt;Before executing any command, it's important to understand Terraform's workflow.&lt;/p&gt;

&lt;p&gt;Terraform follows a simple sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write Configuration

        ↓

terraform init

        ↓

terraform fmt

        ↓

terraform validate

        ↓

terraform plan

        ↓

terraform apply

        ↓

terraform output

        ↓

terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following this workflow ensures that the infrastructure is created safely and consistently.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Step 1 — Initialize Terraform
&lt;/h1&gt;

&lt;p&gt;The very first command executed in every Terraform project is:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This command initializes the current working directory.&lt;/p&gt;

&lt;p&gt;During initialization Terraform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downloads required providers&lt;/li&gt;
&lt;li&gt;Creates the &lt;code&gt;.terraform&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;Creates the provider lock file&lt;/li&gt;
&lt;li&gt;Prepares the project for execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If initialization is successful, Terraform displays a success message.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;terraform init&lt;/code&gt; is mandatory before executing any other Terraform command.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffouz5vd6p5q3ftcv7izo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffouz5vd6p5q3ftcv7izo.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ✅ Step 2 — Validate Configuration
&lt;/h1&gt;

&lt;p&gt;Once Terraform is initialized, the next step is validating the configuration.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Validation checks the configuration for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syntax errors&lt;/li&gt;
&lt;li&gt;Invalid references&lt;/li&gt;
&lt;li&gt;Missing blocks&lt;/li&gt;
&lt;li&gt;Configuration mistakes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything is correct, Terraform displays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Success! The configuration is valid.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running validation before deployment helps detect mistakes early.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fisg282e4o0i9bgxfegmp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fisg282e4o0i9bgxfegmp.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📋 Step 3 — Preview Infrastructure
&lt;/h1&gt;

&lt;p&gt;Before creating infrastructure, Terraform allows us to preview every planned change.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;The execution plan displayed the following actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the Nginx Docker image.&lt;/li&gt;
&lt;li&gt;Create a Docker container.&lt;/li&gt;
&lt;li&gt;Configure the required port mapping.&lt;/li&gt;
&lt;li&gt;Generate output values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end of the execution plan, Terraform summarized the changes.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan: 2 to add, 0 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reviewing the execution plan before deployment is considered one of Terraform's best practices because it allows us to verify the changes before they are applied.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe2tobrmb11cp7ykfwjsn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe2tobrmb11cp7ykfwjsn.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Step 4 — Apply Configuration
&lt;/h1&gt;

&lt;p&gt;After verifying the execution plan, the infrastructure was deployed using:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform displayed a confirmation prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do you want to perform these actions?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After typing:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform performed the following tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pulled the latest Nginx image.&lt;/li&gt;
&lt;li&gt;Created the Docker container.&lt;/li&gt;
&lt;li&gt;Exposed port &lt;strong&gt;8080&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Generated output values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After a few seconds, Terraform displayed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apply complete!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the infrastructure had been successfully created.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcvp1m4c8fw082saj2gpq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcvp1m4c8fw082saj2gpq.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🐳 Verifying the Running Container
&lt;/h1&gt;

&lt;p&gt;After deployment, I verified that the Docker container was actually running.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;This command lists all currently running Docker containers.&lt;/p&gt;

&lt;p&gt;The output confirmed that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Nginx image was downloaded.&lt;/li&gt;
&lt;li&gt;The container was running successfully.&lt;/li&gt;
&lt;li&gt;Port &lt;strong&gt;8080&lt;/strong&gt; was mapped correctly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verifying the container is a good practice before testing the application in a browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fftb3xe92v5erqiw420bk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fftb3xe92v5erqiw420bk.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🌐 Accessing the Nginx Application
&lt;/h1&gt;

&lt;p&gt;Once the container was running, I opened the following URL in my browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default &lt;strong&gt;Welcome to nginx!&lt;/strong&gt; page appeared successfully.&lt;/p&gt;

&lt;p&gt;This confirmed that Terraform had successfully deployed and configured the Docker container.&lt;/p&gt;

&lt;p&gt;It was satisfying to see the infrastructure working exactly as expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6vo8nq695e260a2svipa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6vo8nq695e260a2svipa.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📤 Viewing Terraform Outputs
&lt;/h1&gt;

&lt;p&gt;Terraform Outputs display useful information after infrastructure has been created.&lt;/p&gt;

&lt;p&gt;Instead of manually checking the container configuration, Terraform automatically displayed the required values.&lt;/p&gt;

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

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;container_name = "tws-web"

access_url = "http://localhost:8080"

image = "nginx:latest"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outputs are extremely useful because they can also be consumed by other Terraform modules or CI/CD pipelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fslgqqmlfto3av878f4cg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fslgqqmlfto3av878f4cg.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  📊 Understanding Variable Precedence
&lt;/h1&gt;

&lt;p&gt;Terraform variables can receive values from multiple sources.&lt;/p&gt;

&lt;p&gt;If the same variable exists in more than one location, Terraform follows a fixed precedence order.&lt;/p&gt;

&lt;p&gt;The highest priority source always wins.&lt;br&gt;
&lt;/p&gt;

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

      ↓

-var-file

      ↓

*.auto.tfvars

      ↓

terraform.tfvars

      ↓

TF_VAR_ Environment Variables

      ↓

Default Values
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Understanding variable precedence is important because it allows the same Terraform configuration to be reused across multiple environments without modifying the code.&lt;/p&gt;




&lt;h1&gt;
  
  
  🍫 Bonus Exploration
&lt;/h1&gt;

&lt;p&gt;After completing the required tasks, I explored a few advanced HCL features.&lt;/p&gt;

&lt;p&gt;These features make Terraform configurations cleaner and more powerful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bonus 1 — For Expressions
&lt;/h2&gt;

&lt;p&gt;Terraform provides &lt;strong&gt;For Expressions&lt;/strong&gt; to transform collections.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;upper_labels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;

    &lt;span class="nx"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="nx"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"docker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"terraform"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"nginx"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;

    &lt;span class="nx"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;label&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;Instead of transforming each value manually, Terraform automatically iterates through every element.&lt;/p&gt;

&lt;p&gt;This feature becomes extremely useful while working with Lists and Maps.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F02cdkuv737ns7mp5wh8o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F02cdkuv737ns7mp5wh8o.png" alt=" " width="799" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Bonus 2 — Conditional Expressions
&lt;/h2&gt;

&lt;p&gt;Conditional Expressions work similarly to an &lt;strong&gt;if-else&lt;/strong&gt; statement.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="err"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"prod"&lt;/span&gt;

&lt;span class="err"&gt;?&lt;/span&gt;

&lt;span class="s2"&gt;"large"&lt;/span&gt;

&lt;span class="err"&gt;:&lt;/span&gt;

&lt;span class="s2"&gt;"small"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the environment is Production, Terraform returns:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

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

&lt;/div&gt;



&lt;p&gt;Conditional expressions help create reusable configurations for different deployment environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw9klb5v9v8qhdy289bhn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw9klb5v9v8qhdy289bhn.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Bonus 3 — Optional Object Attributes
&lt;/h2&gt;

&lt;p&gt;Terraform also supports optional attributes inside Object types.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"container_config"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;

    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;

    &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8080&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;If the port value is not supplied, Terraform automatically assigns the default value of &lt;strong&gt;8080&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This feature helps create flexible object definitions without forcing users to specify every attribute.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧹 Destroying Infrastructure
&lt;/h1&gt;

&lt;p&gt;Once the testing was completed, I removed all the resources created by Terraform.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Terraform again displayed a confirmation prompt.&lt;/p&gt;

&lt;p&gt;After typing:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Terraform removed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Container&lt;/li&gt;
&lt;li&gt;Docker Image (if configured)&lt;/li&gt;
&lt;li&gt;Terraform-managed resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, Terraform displayed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destroy complete!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Destroying unused infrastructure is a good practice because it keeps the environment clean and avoids unnecessary resource usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  📸 Screenshot
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4kp3ny9wk5hbbppg1z68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4kp3ny9wk5hbbppg1z68.png" alt=" " width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 What I Learned
&lt;/h1&gt;

&lt;p&gt;Day 2 helped me understand the actual language behind Terraform.&lt;/p&gt;

&lt;p&gt;Some of the key takeaways from today's challenge are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learned how Terraform configurations are written using HCL.&lt;/li&gt;
&lt;li&gt;Understood the purpose of Blocks, Arguments, and Expressions.&lt;/li&gt;
&lt;li&gt;Explored all major Terraform Variable Types.&lt;/li&gt;
&lt;li&gt;Applied Validation Rules to improve configuration reliability.&lt;/li&gt;
&lt;li&gt;Protected confidential values using Sensitive Variables.&lt;/li&gt;
&lt;li&gt;Used Locals to avoid duplicate code.&lt;/li&gt;
&lt;li&gt;Worked with Terraform Outputs.&lt;/li&gt;
&lt;li&gt;Explored useful built-in Functions.&lt;/li&gt;
&lt;li&gt;Used Terraform Console to experiment with expressions.&lt;/li&gt;
&lt;li&gt;Understood Variable Precedence.&lt;/li&gt;
&lt;li&gt;Successfully deployed an Nginx Docker container using Terraform.&lt;/li&gt;
&lt;li&gt;Explored advanced HCL concepts like For Expressions, Conditional Expressions, and Optional Object Attributes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, today's challenge gave me a much stronger understanding of writing reusable and production-ready Terraform configurations.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 Conclusion
&lt;/h1&gt;

&lt;p&gt;Day 2 marked an important milestone in my Terraform learning journey.&lt;/p&gt;

&lt;p&gt;While Day 1 introduced the fundamentals of Infrastructure as Code, today's challenge focused on writing clean, reusable, and maintainable Terraform configurations using HCL.&lt;/p&gt;

&lt;p&gt;From understanding variables and expressions to deploying a real Docker container and exploring advanced HCL features, every concept contributed to building a stronger foundation in Terraform.&lt;/p&gt;

&lt;p&gt;I'm excited to continue the TerraWeek Challenge and dive deeper into modules, state management, and cloud infrastructure in the upcoming days.&lt;/p&gt;




&lt;h1&gt;
  
  
  🏷️ Tags
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;#Terraform&lt;/code&gt; &lt;code&gt;#HashiCorp&lt;/code&gt; &lt;code&gt;#InfrastructureAsCode&lt;/code&gt; &lt;code&gt;#Docker&lt;/code&gt; &lt;code&gt;#DevOps&lt;/code&gt; &lt;code&gt;#HCL&lt;/code&gt; &lt;code&gt;#IaC&lt;/code&gt; &lt;code&gt;#TrainWithShubham&lt;/code&gt; &lt;code&gt;#TerraWeekChallenge&lt;/code&gt;&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>trainwithshubham</category>
      <category>terraweekchallenge</category>
    </item>
    <item>
      <title>Day 1 of #TerraWeek — From Zero to First `terraform init`</title>
      <dc:creator>Kshitij Sharma</dc:creator>
      <pubDate>Sun, 12 Jul 2026 10:46:45 +0000</pubDate>
      <link>https://dev.to/kshitij_sharma_fd33fdb032/day-1-of-terraweek-from-zero-to-first-terraform-init-2aff</link>
      <guid>https://dev.to/kshitij_sharma_fd33fdb032/day-1-of-terraweek-from-zero-to-first-terraform-init-2aff</guid>
      <description>&lt;h1&gt;
  
  
  🌱 TerraWeek Challenge – Day 1
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction to Infrastructure as Code (IaC) &amp;amp; Terraform Basics
&lt;/h2&gt;

&lt;p&gt;📅 &lt;strong&gt;Date:&lt;/strong&gt; 12 July 2026&lt;/p&gt;

&lt;p&gt;Welcome to &lt;strong&gt;Day 1&lt;/strong&gt; of my &lt;strong&gt;TerraWeek Challenge&lt;/strong&gt;! 🚀&lt;/p&gt;

&lt;p&gt;Today was all about understanding &lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt;, learning the fundamentals of &lt;strong&gt;Terraform&lt;/strong&gt;, and provisioning my first resource locally. Although the project itself was simple, it helped me understand the workflow that powers modern infrastructure automation.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎯 Learning Objectives
&lt;/h1&gt;

&lt;p&gt;By the end of Day 1, I was able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand what Infrastructure as Code (IaC) is.&lt;/li&gt;
&lt;li&gt;Learn why Terraform is one of the most popular IaC tools.&lt;/li&gt;
&lt;li&gt;Install and configure Terraform.&lt;/li&gt;
&lt;li&gt;Learn Terraform's core workflow.&lt;/li&gt;
&lt;li&gt;Understand important Terraform concepts.&lt;/li&gt;
&lt;li&gt;Create and destroy my first infrastructure.&lt;/li&gt;
&lt;li&gt;Explore OpenTofu and Terraform's lock file.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  📖 Why Infrastructure as Code?
&lt;/h1&gt;

&lt;p&gt;Before writing any Terraform configuration, I wanted to understand &lt;strong&gt;why Infrastructure as Code exists&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Managing cloud infrastructure manually through a web console may work for a personal project, but it quickly becomes difficult as projects grow.&lt;/p&gt;

&lt;p&gt;Some common problems with manual infrastructure are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Human errors while configuring resources.&lt;/li&gt;
&lt;li&gt;Difficulty recreating the exact same environment.&lt;/li&gt;
&lt;li&gt;Poor collaboration among teams.&lt;/li&gt;
&lt;li&gt;No version history for infrastructure changes.&lt;/li&gt;
&lt;li&gt;Slow deployments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Infrastructure as Code solves these problems by allowing infrastructure to be written, reviewed, and version-controlled just like application code.&lt;/p&gt;

&lt;p&gt;Instead of remembering every click in a cloud console, everything is defined inside configuration files that can be executed repeatedly.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌍 What is Terraform?
&lt;/h1&gt;

&lt;p&gt;Terraform is an open-source &lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt; tool developed by HashiCorp.&lt;/p&gt;

&lt;p&gt;It uses &lt;strong&gt;HashiCorp Configuration Language (HCL)&lt;/strong&gt; to describe the desired infrastructure, and Terraform automatically determines the changes required to reach that desired state.&lt;/p&gt;

&lt;p&gt;One of Terraform's biggest strengths is that it is &lt;strong&gt;provider agnostic&lt;/strong&gt;, meaning the same tool can manage resources across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS&lt;/li&gt;
&lt;li&gt;Azure&lt;/li&gt;
&lt;li&gt;Google Cloud&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Cloudflare&lt;/li&gt;
&lt;li&gt;DigitalOcean&lt;/li&gt;
&lt;li&gt;VMware&lt;/li&gt;
&lt;li&gt;Hundreds of other providers&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⭐ Why Terraform?
&lt;/h1&gt;

&lt;p&gt;Terraform has become one of the industry's most widely adopted Infrastructure as Code tools because it offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declarative configuration&lt;/li&gt;
&lt;li&gt;Multi-cloud support&lt;/li&gt;
&lt;li&gt;Huge provider ecosystem&lt;/li&gt;
&lt;li&gt;State management&lt;/li&gt;
&lt;li&gt;Reusable modules&lt;/li&gt;
&lt;li&gt;Version-controlled infrastructure&lt;/li&gt;
&lt;li&gt;Easy CI/CD integration&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⚖️ Terraform vs Alternatives
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Comparison&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Terraform&lt;/td&gt;
&lt;td&gt;Multi-cloud Infrastructure as Code using HCL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenTofu&lt;/td&gt;
&lt;td&gt;Community-driven open-source fork of Terraform&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pulumi&lt;/td&gt;
&lt;td&gt;Uses programming languages like Python and Go instead of HCL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloudFormation&lt;/td&gt;
&lt;td&gt;AWS-only Infrastructure as Code service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ansible&lt;/td&gt;
&lt;td&gt;Primarily used for configuration management rather than provisioning infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  🛠 Installing Terraform
&lt;/h1&gt;

&lt;p&gt;The first practical step was installing the latest version of Terraform.&lt;/p&gt;

&lt;p&gt;After installation, I verified everything using:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Terraform Version
&lt;/h2&gt;

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




&lt;h2&gt;
  
  
  Terraform Help
&lt;/h2&gt;

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




&lt;h2&gt;
  
  
  VS Code Extension
&lt;/h2&gt;

&lt;p&gt;To improve the development experience, I installed the official &lt;strong&gt;HashiCorp Terraform Extension&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syntax Highlighting&lt;/li&gt;
&lt;li&gt;IntelliSense&lt;/li&gt;
&lt;li&gt;Auto Completion&lt;/li&gt;
&lt;li&gt;Formatting&lt;/li&gt;
&lt;li&gt;Validation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Screenshot
&lt;/h3&gt;

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

&lt;h1&gt;
  
  
  📘 Important Terraform Terminologies
&lt;/h1&gt;

&lt;p&gt;Before creating any infrastructure, I learned the six core concepts that form the foundation of every Terraform project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provider
&lt;/h2&gt;

&lt;p&gt;A provider is a plugin that allows Terraform to communicate with a specific platform.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ap-south-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Resource
&lt;/h2&gt;

&lt;p&gt;A resource represents any infrastructure object managed by Terraform.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"local_file"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hello.txt"&lt;/span&gt;
  &lt;span class="nx"&gt;content&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello Terraform"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  State
&lt;/h2&gt;

&lt;p&gt;Terraform stores information about all managed resources inside a file named:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The state file allows Terraform to understand what already exists and what changes need to be made.&lt;/p&gt;




&lt;h2&gt;
  
  
  Plan
&lt;/h2&gt;

&lt;p&gt;Before applying any changes, Terraform generates an execution plan showing exactly what will happen.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This provides an additional safety check before modifying infrastructure.&lt;/p&gt;




&lt;h2&gt;
  
  
  HCL
&lt;/h2&gt;

&lt;p&gt;HCL (HashiCorp Configuration Language) is the language used to write Terraform configurations.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"random_pet"&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Module
&lt;/h2&gt;

&lt;p&gt;A module is a reusable collection of Terraform configuration.&lt;/p&gt;

&lt;p&gt;Instead of rewriting the same infrastructure repeatedly, modules allow configurations to be packaged and reused.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"network"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/network"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🚀 My First Terraform Workflow
&lt;/h1&gt;

&lt;p&gt;The challenge uses the &lt;strong&gt;local&lt;/strong&gt; and &lt;strong&gt;random&lt;/strong&gt; providers, allowing me to learn Terraform without needing a cloud account.&lt;/p&gt;

&lt;p&gt;I followed the complete Terraform workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1 – Initialize Terraform
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;Terraform downloaded the required providers and initialized the project.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  Step 2 – Format Code
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;Automatically formatted the Terraform configuration files.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3 – Validate Configuration
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;Terraform checked the configuration for syntax errors.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  Step 4 – Preview Changes
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;Terraform displayed the execution plan before creating any resources.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Step 5 – Apply Configuration
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;Terraform created the required resources.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  Generated Output
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;greeting.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The local file was successfully created.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  Step 6 – Destroy Infrastructure
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;Terraform removed every resource it had created.&lt;/p&gt;

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




&lt;h1&gt;
  
  
  🔄 Terraform Workflow
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write Configuration
        │
        ▼
terraform init
        │
        ▼
terraform fmt
        │
        ▼
terraform validate
        │
        ▼
terraform plan
        │
        ▼
terraform apply
        │
        ▼
terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🍫 Bonus Exploration
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Enable CLI Autocomplete
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform &lt;span class="nt"&gt;-install-autocomplete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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




&lt;h2&gt;
  
  
  OpenTofu
&lt;/h2&gt;

&lt;p&gt;OpenTofu is a community-driven fork of Terraform that remains fully open source while maintaining compatibility with existing Terraform configurations.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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




&lt;h2&gt;
  
  
  Understanding &lt;code&gt;.terraform.lock.hcl&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;During initialization, Terraform generated a file named:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.terraform.lock.hcl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file records:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provider versions&lt;/li&gt;
&lt;li&gt;Provider checksums&lt;/li&gt;
&lt;li&gt;Dependency information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tracking this file in Git ensures that every developer and CI/CD pipeline uses the exact same provider versions.&lt;/p&gt;

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




&lt;h1&gt;
  
  
  💡 Key Takeaways
&lt;/h1&gt;

&lt;p&gt;Day 1 helped me understand that Terraform is much more than a provisioning tool.&lt;/p&gt;

&lt;p&gt;The biggest lesson was learning how Infrastructure as Code brings consistency, automation, and version control to infrastructure management. Even with a simple local project, I experienced Terraform's complete lifecycle—from initialization to clean destruction of resources.&lt;/p&gt;

&lt;p&gt;This foundation will make it much easier to build real cloud infrastructure in the upcoming TerraWeek sessions.&lt;/p&gt;




&lt;h1&gt;
  
  
  📂 Project Structure
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Day-01/
│── README.md
│── example/
│── images/
│   ├── terraform-version.png
│   ├── terraform-help.png
│   ├── vscode-extension.png
│   ├── init.png
│   ├── fmt.png
│   ├── validate.png
│   ├── plan.png
│   ├── apply.png
│   ├── greeting.png
│   ├── destroy.png
│   ├── autocomplete.png
│   ├── opentofu-version.png
│   └── lock-file.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🚀 Conclusion
&lt;/h1&gt;

&lt;p&gt;Day 1 laid the foundation for my Terraform journey. I learned why Infrastructure as Code has become an essential DevOps practice, explored Terraform's core concepts, completed my first Terraform workflow, and understood how infrastructure can be managed in a consistent, repeatable, and version-controlled way.&lt;/p&gt;

&lt;p&gt;Looking forward to Day 2, where I'll dive deeper into HCL, variables, expressions, and reusable configurations.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏷️ Tags
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;#Terraform&lt;/code&gt; &lt;code&gt;#InfrastructureAsCode&lt;/code&gt; &lt;code&gt;#DevOps&lt;/code&gt; &lt;code&gt;#HashiCorp&lt;/code&gt; &lt;code&gt;#OpenTofu&lt;/code&gt; &lt;code&gt;#GitHub&lt;/code&gt; &lt;code&gt;#CloudComputing&lt;/code&gt; &lt;code&gt;#TrainWithShubham&lt;/code&gt; &lt;code&gt;#TerraWeekChallenge&lt;/code&gt;&lt;/p&gt;

</description>
      <category>trainwithshubham</category>
      <category>terraweekchallenge</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Why is it important to make a good api rather than a clean api</title>
      <dc:creator>Kshitij Sharma</dc:creator>
      <pubDate>Thu, 23 Apr 2026 09:25:56 +0000</pubDate>
      <link>https://dev.to/kshitij_sharma_fd33fdb032/why-is-it-important-to-make-a-good-api-rather-than-a-clean-api-5bmk</link>
      <guid>https://dev.to/kshitij_sharma_fd33fdb032/why-is-it-important-to-make-a-good-api-rather-than-a-clean-api-5bmk</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kshitij_sharma_fd33fdb032/when-your-clean-rest-api-becomes-a-production-nightmare-33hl" class="crayons-story__hidden-navigation-link"&gt;When Your “Clean” REST API Becomes a Production Nightmare&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/kshitij_sharma_fd33fdb032" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3892871%2Fb33f228c-f438-4022-9db2-6b287297b3c4.png" alt="kshitij_sharma_fd33fdb032 profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kshitij_sharma_fd33fdb032" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Kshitij Sharma
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Kshitij Sharma
                
              
              &lt;div id="story-author-preview-content-3539092" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kshitij_sharma_fd33fdb032" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3892871%2Fb33f228c-f438-4022-9db2-6b287297b3c4.png" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Kshitij Sharma&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kshitij_sharma_fd33fdb032/when-your-clean-rest-api-becomes-a-production-nightmare-33hl" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 23&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kshitij_sharma_fd33fdb032/when-your-clean-rest-api-becomes-a-production-nightmare-33hl" id="article-link-3539092"&gt;
          When Your “Clean” REST API Becomes a Production Nightmare
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/api"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;api&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/backend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;backend&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/systemdesign"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;systemdesign&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kshitij_sharma_fd33fdb032/when-your-clean-rest-api-becomes-a-production-nightmare-33hl" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kshitij_sharma_fd33fdb032/when-your-clean-rest-api-becomes-a-production-nightmare-33hl#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>When Your “Clean” REST API Becomes a Production Nightmare</title>
      <dc:creator>Kshitij Sharma</dc:creator>
      <pubDate>Thu, 23 Apr 2026 04:41:21 +0000</pubDate>
      <link>https://dev.to/kshitij_sharma_fd33fdb032/when-your-clean-rest-api-becomes-a-production-nightmare-33hl</link>
      <guid>https://dev.to/kshitij_sharma_fd33fdb032/when-your-clean-rest-api-becomes-a-production-nightmare-33hl</guid>
      <description>&lt;p&gt;Everything looked perfect on paper.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean endpoints&lt;/li&gt;
&lt;li&gt;Nice resource naming&lt;/li&gt;
&lt;li&gt;Proper HTTP methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then production hit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clients started retrying aggressively&lt;/li&gt;
&lt;li&gt;Data inconsistencies appeared&lt;/li&gt;
&lt;li&gt;Versioning became a mess&lt;/li&gt;
&lt;li&gt;One change broke 3 consumers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s when reality kicks in:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;REST API design is not about elegance — it’s about survivability under change.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  The Real Constraints of REST APIs in Production
&lt;/h1&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%2Fmhy8toz7b70gi4krjywg.jpg" 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%2Fmhy8toz7b70gi4krjywg.jpg" alt=" " width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’re not designing endpoints.&lt;br&gt;
You’re designing &lt;strong&gt;contracts under uncertainty&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What actually shapes your API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple clients (web, mobile, third-party)&lt;/li&gt;
&lt;li&gt;Network unreliability&lt;/li&gt;
&lt;li&gt;Backward compatibility pressure&lt;/li&gt;
&lt;li&gt;Partial failures&lt;/li&gt;
&lt;li&gt;Latency budgets&lt;/li&gt;
&lt;li&gt;Data ownership boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ignoring these = brittle APIs that collapse under scale.&lt;/p&gt;


&lt;h1&gt;
  
  
  Resource Modeling Is Where Most People Fail
&lt;/h1&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%2Foqv2pmkev2qrnwood05y.jpg" 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%2Foqv2pmkev2qrnwood05y.jpg" alt=" " width="539" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everyone talks about &lt;code&gt;/users&lt;/code&gt; and &lt;code&gt;/orders&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That’s surface-level.&lt;/p&gt;

&lt;p&gt;The real question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What is the lifecycle of your resource?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Bad Design (naive CRUD mindset)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /orders
GET /orders/:id
PUT /orders/:id
DELETE /orders/:id
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Looks fine. Completely wrong for real systems.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Orders aren’t freely mutable&lt;/li&gt;
&lt;li&gt;State transitions matter (created → paid → shipped)&lt;/li&gt;
&lt;li&gt;Business rules are ignored&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;
  
  
  Model State Transitions Explicitly
&lt;/h1&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST   /orders
POST   /orders/:id/pay
POST   /orders/:id/ship
POST   /orders/:id/cancel
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You encode business logic in API&lt;/li&gt;
&lt;li&gt;You prevent invalid transitions&lt;/li&gt;
&lt;li&gt;You reduce client-side bugs&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Idempotency: The Thing That Saves You From Chaos
&lt;/h1&gt;

&lt;p&gt;Most APIs break under retries.&lt;/p&gt;

&lt;p&gt;Reality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clients retry&lt;/li&gt;
&lt;li&gt;Proxies retry&lt;/li&gt;
&lt;li&gt;Load balancers retry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your endpoint isn’t idempotent → duplicate operations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Failure Case
&lt;/h2&gt;

&lt;p&gt;Payment API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /payments
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Client times out → retries → duplicate charge.&lt;/p&gt;

&lt;p&gt;Congrats, you just lost user trust.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fix: Idempotency Keys
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /payments
Idempotency-Key: 8f3a-xyz-123
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idempotencyKey&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;previousResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;storeResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idempotencyKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Partial Failure Handling (The Silent Killer)
&lt;/h1&gt;

&lt;p&gt;Your API calls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DB&lt;/li&gt;
&lt;li&gt;Cache&lt;/li&gt;
&lt;li&gt;External service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One fails.&lt;/p&gt;

&lt;p&gt;Now what?&lt;/p&gt;

&lt;p&gt;Most APIs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Return 500 and pray.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s not a strategy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Better Approach: Explicit Failure Semantics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Return partial success where valid&lt;/li&gt;
&lt;li&gt;Use compensating actions&lt;/li&gt;
&lt;li&gt;Log correlation IDs&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"partial_success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"failed_dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"inventory-service"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Versioning: Where APIs Go to Die
&lt;/h1&gt;

&lt;p&gt;Naive approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/v1/users
/v2/users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You now maintain 2 systems forever&lt;/li&gt;
&lt;li&gt;Clients don’t migrate&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Better Strategy: Evolution Over Versioning
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add fields, don’t remove&lt;/li&gt;
&lt;li&gt;Use default values&lt;/li&gt;
&lt;li&gt;Deprecate gradually&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When Versioning Is Actually Needed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Breaking contract changes&lt;/li&gt;
&lt;li&gt;Semantic shifts (not just fields)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even then:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer header-based versioning&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: application/vnd.myapi.v2+json
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Overfetching vs Underfetching
&lt;/h1&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%2Fvp0lxyp0n26iaslyxcdl.jpg" 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%2Fvp0lxyp0n26iaslyxcdl.jpg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Classic REST problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Overfetching
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /users/:id
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name&lt;/li&gt;
&lt;li&gt;Email&lt;/li&gt;
&lt;li&gt;Address&lt;/li&gt;
&lt;li&gt;Preferences&lt;/li&gt;
&lt;li&gt;Activity logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Client only needs name.&lt;/p&gt;

&lt;p&gt;Waste:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bandwidth&lt;/li&gt;
&lt;li&gt;latency&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Underfetching
&lt;/h2&gt;

&lt;p&gt;Client needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user&lt;/li&gt;
&lt;li&gt;orders&lt;/li&gt;
&lt;li&gt;payments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Makes 3 calls.&lt;/p&gt;

&lt;p&gt;Now latency multiplies.&lt;/p&gt;




&lt;h2&gt;
  
  
  Practical Fix: Controlled Expansion
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /users/:id?include=orders,payments
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trade-off:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More complex backend&lt;/li&gt;
&lt;li&gt;Better client efficiency&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Implementation: What a Production-Ready API Looks Like
&lt;/h1&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%2F10qnhnk52hn2rx8pnhzq.jpg" 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%2F10qnhnk52hn2rx8pnhzq.jpg" alt=" " width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Express.js Example (Opinionated Structure)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Middleware: request ID for tracing&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Idempotency middleware&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/payments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;idempotency-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Explicit state transition&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/orders/:id/ship&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid state&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;shipOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shipped&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Common Mistakes That Kill APIs
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ❌ Treating REST Like CRUD
&lt;/h2&gt;

&lt;p&gt;You ignore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;business logic&lt;/li&gt;
&lt;li&gt;state transitions&lt;/li&gt;
&lt;li&gt;invariants&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ❌ Ignoring Timeouts and Retries
&lt;/h2&gt;

&lt;p&gt;Your system works… until network instability hits.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ No Observability
&lt;/h2&gt;

&lt;p&gt;No:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;request IDs&lt;/li&gt;
&lt;li&gt;structured logs&lt;/li&gt;
&lt;li&gt;tracing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Debugging becomes guessing.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ Tight Coupling to DB Schema
&lt;/h2&gt;

&lt;p&gt;Changing DB → breaks API&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;API is a contract, not a reflection of your database&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ❌ Overusing HTTP Status Codes
&lt;/h2&gt;

&lt;p&gt;People do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;200 OK (with error inside body)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;500 for everything
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both are wrong.&lt;/p&gt;




&lt;h1&gt;
  
  
  Trade-offs You Can’t Escape
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Flexibility vs Simplicity
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Flexible APIs → harder to maintain&lt;/li&gt;
&lt;li&gt;Simple APIs → limited use cases&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Performance vs Consistency
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Strong consistency → slower&lt;/li&gt;
&lt;li&gt;Eventual consistency → complex&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Versioning vs Evolution
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Versioning → fragmentation&lt;/li&gt;
&lt;li&gt;Evolution → constraints on change&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Abstraction vs Control
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;High abstraction → easy usage&lt;/li&gt;
&lt;li&gt;Low abstraction → better performance&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  What a Mature REST API Actually Looks Like
&lt;/h1&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%2Fylppy7ge24wotdqiyzbx.jpg" 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%2Fylppy7ge24wotdqiyzbx.jpg" alt=" " width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explicit state transitions&lt;/li&gt;
&lt;li&gt;Idempotent operations&lt;/li&gt;
&lt;li&gt;Backward-compatible changes&lt;/li&gt;
&lt;li&gt;Observability baked in&lt;/li&gt;
&lt;li&gt;Controlled data fetching&lt;/li&gt;
&lt;li&gt;Failure-aware responses&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Final Reality Check
&lt;/h1&gt;

&lt;p&gt;If your API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;breaks on retries&lt;/li&gt;
&lt;li&gt;can’t evolve without versioning chaos&lt;/li&gt;
&lt;li&gt;hides business logic&lt;/li&gt;
&lt;li&gt;lacks observability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s not production-ready.&lt;/p&gt;




&lt;h1&gt;
  
  
  Key Takeaways
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;REST is not CRUD — it’s contract design under failure&lt;/li&gt;
&lt;li&gt;Idempotency is non-negotiable&lt;/li&gt;
&lt;li&gt;State transitions must be explicit&lt;/li&gt;
&lt;li&gt;Versioning is a last resort, not default&lt;/li&gt;
&lt;li&gt;Most failures come from network behavior, not code&lt;/li&gt;
&lt;li&gt;API design is about handling &lt;em&gt;bad conditions&lt;/em&gt;, not ideal flows&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you design APIs assuming everything works perfectly,&lt;br&gt;
your system will fail the moment it doesn’t.&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>systemdesign</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Understand the mechanism behind the api failing randomly</title>
      <dc:creator>Kshitij Sharma</dc:creator>
      <pubDate>Wed, 22 Apr 2026 17:41:09 +0000</pubDate>
      <link>https://dev.to/kshitij_sharma_fd33fdb032/understand-the-mechanism-behind-the-api-failing-randomly-2mci</link>
      <guid>https://dev.to/kshitij_sharma_fd33fdb032/understand-the-mechanism-behind-the-api-failing-randomly-2mci</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/kshitij_sharma_fd33fdb032/when-your-api-randomly-starts-timing-out-6a3" class="crayons-story__hidden-navigation-link"&gt;When Your API “Randomly” Starts Timing Out&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/kshitij_sharma_fd33fdb032" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3892871%2Fb33f228c-f438-4022-9db2-6b287297b3c4.png" alt="kshitij_sharma_fd33fdb032 profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/kshitij_sharma_fd33fdb032" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Kshitij Sharma
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Kshitij Sharma
                
              
              &lt;div id="story-author-preview-content-3537617" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/kshitij_sharma_fd33fdb032" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3892871%2Fb33f228c-f438-4022-9db2-6b287297b3c4.png" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Kshitij Sharma&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/kshitij_sharma_fd33fdb032/when-your-api-randomly-starts-timing-out-6a3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 22&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/kshitij_sharma_fd33fdb032/when-your-api-randomly-starts-timing-out-6a3" id="article-link-3537617"&gt;
          When Your API “Randomly” Starts Timing Out
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/backend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;backend&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/networking"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;networking&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/distributedsystems"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;distributedsystems&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/kshitij_sharma_fd33fdb032/when-your-api-randomly-starts-timing-out-6a3" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/kshitij_sharma_fd33fdb032/when-your-api-randomly-starts-timing-out-6a3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>When Your API “Randomly” Starts Timing Out</title>
      <dc:creator>Kshitij Sharma</dc:creator>
      <pubDate>Wed, 22 Apr 2026 17:30:48 +0000</pubDate>
      <link>https://dev.to/kshitij_sharma_fd33fdb032/when-your-api-randomly-starts-timing-out-6a3</link>
      <guid>https://dev.to/kshitij_sharma_fd33fdb032/when-your-api-randomly-starts-timing-out-6a3</guid>
      <description>&lt;p&gt;You deploy a perfectly fine service. Load tests passed. Latency looked clean. Then production hits—and suddenly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;P95 latency spikes&lt;/li&gt;
&lt;li&gt;Requests hang without logs&lt;/li&gt;
&lt;li&gt;CPU is fine, memory is fine… but users are screaming&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn’t a “bug.” This is you not understanding the &lt;strong&gt;&lt;em&gt;actual HTTP request lifecycle&lt;/em&gt;&lt;/strong&gt; beyond the textbook diagram.&lt;/p&gt;

&lt;p&gt;If you don’t know what &lt;strong&gt;&lt;em&gt;really&lt;/em&gt;&lt;/strong&gt; happens between a client sending a request and your handler returning a response, you’re flying blind.&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%2F3sn82cip1cu0vf98te3b.jpg" 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%2F3sn82cip1cu0vf98te3b.jpg" alt=" " width="800" height="725"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  HTTP Request Lifecycle — What Actually Happens Under the Hood
&lt;/h2&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%2Fxlemttnwnohmubuj150r.jpg" 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%2Fxlemttnwnohmubuj150r.jpg" alt=" " width="775" height="708"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Forget diagrams like &lt;strong&gt;&lt;em&gt;Client → Server → Response&lt;/em&gt;&lt;/strong&gt;. That’s marketing-level abstraction.&lt;/p&gt;

&lt;p&gt;A real request goes through:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Connection Establishment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;DNS resolution&lt;/li&gt;
&lt;li&gt;TCP handshake (3-way)&lt;/li&gt;
&lt;li&gt;TLS handshake (if HTTPS)&lt;/li&gt;
&lt;li&gt;Connection pooling / reuse (keep-alive)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Kernel → User Space Transition
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;NIC receives packet → kernel buffer&lt;/li&gt;
&lt;li&gt;Socket read readiness via epoll/kqueue&lt;/li&gt;
&lt;li&gt;Data copied into user space buffers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. HTTP Parsing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Raw bytes → protocol parsing (headers, method, path)&lt;/li&gt;
&lt;li&gt;Chunked decoding / content-length validation&lt;/li&gt;
&lt;li&gt;Header normalization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Routing &amp;amp; Middleware Chain
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Path matching (often regex or trie-based)&lt;/li&gt;
&lt;li&gt;Middleware execution (auth, logging, rate limiting)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Business Logic Execution
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;DB calls&lt;/li&gt;
&lt;li&gt;External APIs&lt;/li&gt;
&lt;li&gt;CPU-bound work&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Response Construction
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Serialization (JSON, protobuf, etc.)&lt;/li&gt;
&lt;li&gt;Compression (gzip, brotli)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. Write Back to Socket
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Kernel send buffer&lt;/li&gt;
&lt;li&gt;TCP congestion control&lt;/li&gt;
&lt;li&gt;Potential partial writes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. Connection Lifecycle Decision
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keep-alive reuse vs close&lt;/li&gt;
&lt;li&gt;Idle timeout tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Miss any one of these layers, and you’ll misdiagnose production issues.&lt;/p&gt;




&lt;h1&gt;
  
  
  Where Systems Actually Break
&lt;/h1&gt;

&lt;p&gt;Let’s cut the theory. Real failures:&lt;/p&gt;

&lt;h3&gt;
  
  
  🔴 1. Head-of-Line Blocking in Connection Pools
&lt;/h3&gt;

&lt;p&gt;You think you're async, but your HTTP client pool is exhausted.&lt;/p&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requests queue waiting for a free connection&lt;/li&gt;
&lt;li&gt;Latency explodes without CPU increase&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔴 2. Slow Clients = Resource Leaks
&lt;/h3&gt;

&lt;p&gt;If a client reads slowly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your server keeps buffers open&lt;/li&gt;
&lt;li&gt;Threads/event-loop slots remain occupied&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is &lt;strong&gt;&lt;em&gt;classic slowloris territory&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔴 3. Middleware Abuse
&lt;/h3&gt;

&lt;p&gt;Stacking 10 middlewares sounds clean.&lt;/p&gt;

&lt;p&gt;Reality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each adds latency&lt;/li&gt;
&lt;li&gt;Each may block (logging, auth calls)&lt;/li&gt;
&lt;li&gt;Hard to reason about ordering&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔴 4. TLS Handshake Overhead
&lt;/h3&gt;

&lt;p&gt;Without reuse:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every request pays ~1–2 RTT extra&lt;/li&gt;
&lt;li&gt;CPU spikes due to crypto&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔴 5. Kernel Buffer Backpressure
&lt;/h3&gt;

&lt;p&gt;Your app “sent” the response.&lt;/p&gt;

&lt;p&gt;Kernel says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nope, buffer full. Try later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you ignore this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writes block&lt;/li&gt;
&lt;li&gt;Event loop stalls&lt;/li&gt;
&lt;li&gt;Throughput collapses&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Architecture Decisions That Actually Matter
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Thread-per-request vs Event Loop
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Thread-per-request (e.g., classic Java)
&lt;/h3&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simpler mental model&lt;/li&gt;
&lt;li&gt;Blocking code is fine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Context switching overhead&lt;/li&gt;
&lt;li&gt;Memory per thread (~1MB stack)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Event-driven (Node.js, Netty, Go runtime hybrid)
&lt;/h3&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High concurrency&lt;/li&gt;
&lt;li&gt;Efficient IO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blocking = catastrophic&lt;/li&gt;
&lt;li&gt;Debugging harder&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Reverse Proxy in Front (NGINX / Envoy)
&lt;/h2&gt;

&lt;p&gt;You &lt;strong&gt;&lt;em&gt;should not&lt;/em&gt;&lt;/strong&gt; expose your app server directly.&lt;/p&gt;

&lt;p&gt;Why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handles TLS termination&lt;/li&gt;
&lt;li&gt;Absorbs slow clients&lt;/li&gt;
&lt;li&gt;Better connection management&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Connection Reuse Strategy
&lt;/h2&gt;

&lt;p&gt;Bad:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New TCP per request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Better:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP/1.1 keep-alive&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;HTTP/2 multiplexing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trade-off:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP/2 introduces head-of-line blocking at TCP layer&lt;/li&gt;
&lt;li&gt;QUIC (HTTP/3) fixes it but adds complexity&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Implementation: What This Looks Like in Code
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Example: Minimal HTTP Server (Node.js — showing lifecycle touchpoints)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. Request received (already parsed by Node's HTTP parser)&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. Middleware simulation&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-block&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// simulate bad middleware&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&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="c1"&gt;// 3. Business logic&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responseBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. Response write&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;byteLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseBody&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseBody&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 5. End response (flush to kernel)&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 6. Connection-level tuning&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keepAliveTimeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headersTimeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Where This Code Lies to You
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You don’t see TCP&lt;/li&gt;
&lt;li&gt;You don’t see kernel buffers&lt;/li&gt;
&lt;li&gt;You don’t control backpressure explicitly&lt;/li&gt;
&lt;li&gt;You don’t see partial writes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That abstraction is convenient—and dangerous.&lt;/p&gt;




&lt;h1&gt;
  
  
  Advanced Concern: Backpressure Handling
&lt;/h1&gt;

&lt;p&gt;Most people ignore this. That’s why systems collapse under load.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example (Node.js stream backpressure):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;writeResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canContinue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;canContinue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Kernel buffer full — wait&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;once&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Resumed writing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="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;If you ignore this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory spikes&lt;/li&gt;
&lt;li&gt;Latency spikes&lt;/li&gt;
&lt;li&gt;Eventually crashes&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Failure Case: Timeout Mismatch Hell
&lt;/h1&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%2Fcpzt0mk2bfgd217l2zpq.jpg" 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%2Fcpzt0mk2bfgd217l2zpq.jpg" alt=" " width="637" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load balancer timeout: 60s&lt;/li&gt;
&lt;li&gt;App server timeout: 30s&lt;/li&gt;
&lt;li&gt;DB timeout: 10s&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What happens?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DB times out → app retries&lt;/li&gt;
&lt;li&gt;App still running → LB kills connection&lt;/li&gt;
&lt;li&gt;Client retries → duplicate work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cascade failure&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Trade-offs You Can’t Avoid
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Latency vs Throughput
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Small buffers → lower latency, more syscalls&lt;/li&gt;
&lt;li&gt;Large buffers → better throughput, worse tail latency&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Simplicity vs Control
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Frameworks hide complexity&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;But you lose control over:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;connection reuse&lt;/li&gt;
&lt;li&gt;backpressure&lt;/li&gt;
&lt;li&gt;parsing behavior&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  CPU vs Network Efficiency
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Compression saves bandwidth&lt;/li&gt;
&lt;li&gt;Costs CPU&lt;/li&gt;
&lt;li&gt;Under load, CPU becomes bottleneck&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Keep-Alive vs Resource Locking
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep-alive reduces handshake overhead&lt;/li&gt;
&lt;li&gt;But holds connections longer&lt;/li&gt;
&lt;li&gt;Risk: connection pool exhaustion&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final System Design (What Actually Works in Production)
&lt;/h2&gt;

&lt;p&gt;A sane architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
  ↓
CDN (optional)
  ↓
Reverse Proxy (NGINX / Envoy)
  ↓
App Server (stateless, event-driven)
  ↓
Service Layer
  ↓
Database / Cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terminate TLS early&lt;/li&gt;
&lt;li&gt;Enforce timeouts at every layer&lt;/li&gt;
&lt;li&gt;Use connection pooling aggressively&lt;/li&gt;
&lt;li&gt;Monitor queueing, not just CPU&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaways (No Fluff)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;HTTP lifecycle is mostly &lt;em&gt;not&lt;/em&gt; in your code—it’s in the kernel and network stack&lt;/li&gt;
&lt;li&gt;Most latency issues are queueing problems, not computation problems&lt;/li&gt;
&lt;li&gt;Backpressure is real; ignoring it will kill your system&lt;/li&gt;
&lt;li&gt;Middleware is not free—treat it like production code, not decoration&lt;/li&gt;
&lt;li&gt;Timeouts must be aligned across layers or you create cascading failures&lt;/li&gt;
&lt;li&gt;Keep-alive and pooling are double-edged swords&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you still think HTTP is just “request comes in, response goes out,” you’re not ready to debug production systems.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>webdev</category>
      <category>networking</category>
      <category>distributedsystems</category>
    </item>
  </channel>
</rss>
