<?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>Forem: Sarvar Nadaf</title>
    <description>The latest articles on Forem by Sarvar Nadaf (@sarvar_04).</description>
    <link>https://forem.com/sarvar_04</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1163149%2F5afa2902-591e-4944-b6fa-9bbba80c6e95.png</url>
      <title>Forem: Sarvar Nadaf</title>
      <link>https://forem.com/sarvar_04</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sarvar_04"/>
    <language>en</language>
    <item>
      <title>Deploy Web Servers with Terraform: EC2 + Load Balancer Tutorial</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Mon, 27 Apr 2026 09:40:05 +0000</pubDate>
      <link>https://forem.com/aws-builders/deploy-web-servers-with-terraform-ec2-load-balancer-tutorial-304k</link>
      <guid>https://forem.com/aws-builders/deploy-web-servers-with-terraform-ec2-load-balancer-tutorial-304k</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"A single server is a single point of failure. A load balancer is your insurance policy."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🎯 Welcome Back!
&lt;/h2&gt;

&lt;p&gt;Remember in &lt;a href="https://dev.to/aws-builders/building-your-first-vpc-aws-networking-with-terraform-3h34"&gt;Article 6&lt;/a&gt; when you built your first VPC with public and private subnets? You created the network foundation, but it was empty—no servers, no applications, nothing running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the reality:&lt;/strong&gt; A VPC without compute resources is like building a highway with no cars. You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web servers to run your applications&lt;/li&gt;
&lt;li&gt;A way to handle traffic spikes&lt;/li&gt;
&lt;li&gt;Protection against server failures&lt;/li&gt;
&lt;li&gt;Zero-downtime deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;That's where EC2 instances and Load Balancers come in.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the end of this article, you'll:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Deploy EC2 instances with Terraform&lt;/li&gt;
&lt;li&gt;✅ Configure security groups for web servers&lt;/li&gt;
&lt;li&gt;✅ Use user data to automate server setup&lt;/li&gt;
&lt;li&gt;✅ Create an Application Load Balancer (ALB)&lt;/li&gt;
&lt;li&gt;✅ Implement health checks and target groups&lt;/li&gt;
&lt;li&gt;✅ Build high-availability web infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time Required:&lt;/strong&gt; 45 minutes (20 min read + 25 min practice)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; ~$33/month (~$16 with free tier for ALB)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Difficulty:&lt;/strong&gt; Intermediate&lt;/p&gt;

&lt;p&gt;Let's deploy some real infrastructure! 🚀&lt;/p&gt;


&lt;h2&gt;
  
  
  💔 The Problem: Single Server Syndrome
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Nightmare Scenario
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;It's 2 AM. Your phone rings.&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;Monitoring Alert: Website Down
Status: 503 Service Unavailable
Cause: EC2 instance crashed
Impact: 100% of users affected
Revenue Loss: $500/minute
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You scramble to:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;SSH into the server (if you can)&lt;/li&gt;
&lt;li&gt;Restart the application&lt;/li&gt;
&lt;li&gt;Hope it comes back up&lt;/li&gt;
&lt;li&gt;Watch users leave your site&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The root cause?&lt;/strong&gt; You had &lt;strong&gt;one server&lt;/strong&gt; running everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Single-Server Problems:
&lt;/h3&gt;

&lt;p&gt;❌ &lt;strong&gt;Traffic Spike:&lt;/strong&gt; Black Friday hits, server crashes from load&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Hardware Failure:&lt;/strong&gt; AWS instance dies, site goes down&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Deployment Risk:&lt;/strong&gt; Update breaks something, entire site offline&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;No Redundancy:&lt;/strong&gt; One point of failure = business risk&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Manual Recovery:&lt;/strong&gt; You're the human load balancer at 2 AM&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Poor User Experience:&lt;/strong&gt; Slow response times, timeouts, errors&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sound familiar?&lt;/strong&gt; Let's fix this with load balancing.&lt;/p&gt;


&lt;h2&gt;
  
  
  🌟 What is a Load Balancer? (Quick Theory)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Simple Definition
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Load Balancer&lt;/strong&gt; = Traffic cop for your servers. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Distributes incoming requests across multiple servers&lt;/li&gt;
&lt;li&gt;Monitors server health automatically&lt;/li&gt;
&lt;li&gt;Routes traffic only to healthy servers&lt;/li&gt;
&lt;li&gt;Enables zero-downtime deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Think of it like this:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without Load Balancer:&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;All Users → Single Server → 💥 Overloaded/Crashed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With Load Balancer:&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;Users → Load Balancer → Server 1 (healthy) ✅
                     → Server 2 (healthy) ✅
                     → Server 3 (unhealthy) ❌ (no traffic)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why You Need This
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1: Traffic Spike&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Normal: 100 requests/sec → 2 servers handle it easily&lt;/li&gt;
&lt;li&gt;Black Friday: 10,000 requests/sec → Load balancer distributes across all servers&lt;/li&gt;
&lt;li&gt;Result: Site stays up, users happy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Scenario 2: Server Failure&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server 1 crashes at 2 AM&lt;/li&gt;
&lt;li&gt;Load balancer detects failure in 30 seconds&lt;/li&gt;
&lt;li&gt;Automatically stops sending traffic to Server 1&lt;/li&gt;
&lt;li&gt;Server 2 handles all traffic&lt;/li&gt;
&lt;li&gt;Result: You sleep through the night&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Scenario 3: Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy new code to Server 1&lt;/li&gt;
&lt;li&gt;Load balancer keeps sending traffic to Server 2&lt;/li&gt;
&lt;li&gt;Test Server 1, then switch traffic&lt;/li&gt;
&lt;li&gt;Result: Zero downtime deployment&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📋 Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Completed &lt;a href="https://dev.tolink-to-article-6"&gt;Article 6: Building Your First AWS VPC&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✅ Terraform installed (v1.0+)&lt;/li&gt;
&lt;li&gt;✅ AWS CLI configured&lt;/li&gt;
&lt;li&gt;✅ Basic understanding of VPC and networking&lt;/li&gt;
&lt;li&gt;✅ An SSH key pair in AWS (or we'll create one)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏗️ What We're Building
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Internet
    ↓
Application Load Balancer (ALB)
    ↓
    ├─→ EC2 Instance 1 (Apache)
    └─→ EC2 Instance 2 (Apache)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Architecture Components:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;VPC&lt;/strong&gt; - Our isolated network&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public Subnet&lt;/strong&gt; - Where our resources live&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internet Gateway&lt;/strong&gt; - Internet access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Groups&lt;/strong&gt; - Firewall rules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2 Instances&lt;/strong&gt; - Web servers running Apache&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Load Balancer&lt;/strong&gt; - Traffic distributor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target Group&lt;/strong&gt; - Manages server health&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  📁 Project Structure
&lt;/h2&gt;

&lt;p&gt;Create this folder structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;07-ec2-load-balancer/
├── main.tf           # Main infrastructure code
├── variables.tf      # Input variables
├── outputs.tf        # Output values
└── terraform.tfvars  # Variable values
&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.amazonaws.com%2Fuploads%2Farticles%2F2igrdc5u5wq4g90eiyhl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2igrdc5u5wq4g90eiyhl.png" alt=" " width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Step 1: Define Variables
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;variables.tf&lt;/code&gt;:&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="c1"&gt;# AWS Region&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"aws_region"&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;"AWS region where resources will be created"&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;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Project Name&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"project_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;"Project name for resource naming"&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;"terraform-web"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Environment&lt;/span&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;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Environment name"&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# VPC CIDR&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"vpc_cidr"&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;"CIDR block for VPC"&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;"10.0.0.0/16"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Public Subnet CIDR&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"public_subnet_cidr"&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;"CIDR block for public subnet"&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;"10.0.1.0/24"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Instance Type&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_type"&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;"EC2 instance type"&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;"t2.micro"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Instance Count&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_count"&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;"Number of EC2 instances"&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="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# SSH Key Name&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"key_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;"SSH key pair name"&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;"my-key"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# My IP for SSH Access&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"my_ip"&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;"Your IP address for SSH access (CIDR format)"&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;"0.0.0.0/0"&lt;/span&gt;  &lt;span class="c1"&gt;# Change this to your IP for security&lt;/span&gt;
&lt;span class="p"&gt;}&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.amazonaws.com%2Fuploads%2Farticles%2Fif5m2cl3bo96xf9a27tn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fif5m2cl3bo96xf9a27tn.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;instance_count = 2&lt;/code&gt; - We'll create 2 web servers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;instance_type = "t2.micro"&lt;/code&gt; - Free tier eligible&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;my_ip&lt;/code&gt; - Restrict SSH access (change from 0.0.0.0/0 in production!)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌐 Step 2: Create VPC and Networking
&lt;/h2&gt;

&lt;p&gt;Add to &lt;code&gt;main.tf&lt;/code&gt;:&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="c1"&gt;# Terraform Configuration&lt;/span&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.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; 5.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="c1"&gt;# Provider Configuration&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;span class="c1"&gt;# Data source: Get latest Amazon Linux 2023 AMI&lt;/span&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="nx"&gt;filter&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;"name"&lt;/span&gt;
    &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"al2023-ami-*-x86_64"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;filter&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;"virtualization-type"&lt;/span&gt;
    &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hvm"&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;# Data source: Get available availability zones&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_availability_zones"&lt;/span&gt; &lt;span class="s2"&gt;"available"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"available"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# VPC&lt;/span&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="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;enable_dns_hostnames&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;enable_dns_support&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;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-vpc"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Internet Gateway&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_internet_gateway"&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;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-igw"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Public Subnet&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;cidr_block&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;public_subnet_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;availability_zone&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_availability_zones&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;map_public_ip_on_launch&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;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-public-subnet"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;Type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Public"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Public Route Table&lt;/span&gt;

&lt;span class="c1"&gt;# Public Subnet 2 (Different AZ for ALB)&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"public_2"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&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.2.0/24"&lt;/span&gt;
  &lt;span class="nx"&gt;availability_zone&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_availability_zones&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;map_public_ip_on_launch&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;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-public-subnet-2"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;Type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Public"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table"&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;route&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;"0.0.0.0/0"&lt;/span&gt;
    &lt;span class="nx"&gt;gateway_id&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="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-public-rt"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;Type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Public"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Route Table Association&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table_association"&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt; &lt;span class="p"&gt;{&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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;route_table_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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="c1"&gt;# Route Table Association for Public Subnet 2&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table_association"&lt;/span&gt; &lt;span class="s2"&gt;"public_2"&lt;/span&gt; &lt;span class="p"&gt;{&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_2&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;route_table_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;New Concept: Data Sources&lt;/strong&gt;&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="c1"&gt;# ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;strong&gt;Data sources&lt;/strong&gt; query existing AWS resources. Here we're finding the latest Amazon Linux AMI automatically - no need to hardcode AMI IDs!&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 Step 3: Configure Security Groups
&lt;/h2&gt;

&lt;p&gt;Security groups are like firewalls. Add to &lt;code&gt;main.tf&lt;/code&gt;:&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="c1"&gt;# Security Group for ALB&lt;/span&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;"alb"&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;"${var.project_name}-alb-sg"&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;"Security group for Application Load Balancer"&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;ingress&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;"HTTP from anywhere"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&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;to_port&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;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;egress&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;"Allow all outbound traffic"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"-1"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-alb-sg"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Security Group for EC2 Instances&lt;/span&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;"instance"&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;"${var.project_name}-instance-sg"&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;"Security group for EC2 instances"&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;ingress&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;"HTTP from ALB"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&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;to_port&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;protocol&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
    &lt;span class="nx"&gt;security_groups&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_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alb&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;ingress&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;"SSH from my IP"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&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;my_ip&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;egress&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;"Allow all outbound traffic"&lt;/span&gt;
    &lt;span class="nx"&gt;from_port&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;to_port&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"-1"&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_blocks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-instance-sg"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&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.amazonaws.com%2Fuploads%2Farticles%2Fmv8damni39oo8eticurk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmv8damni39oo8eticurk.png" alt=" " width="796" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Architecture:&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;Internet → ALB (Port 80) → EC2 Instances (Port 80)
                            EC2 Instances (Port 22 from your IP)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Security Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ALB accepts HTTP (80) from anywhere&lt;/li&gt;
&lt;li&gt;EC2 instances only accept HTTP from ALB (not directly from internet!)&lt;/li&gt;
&lt;li&gt;SSH (22) only from your IP address&lt;/li&gt;
&lt;li&gt;This is called "defense in depth"&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🖥️ Step 4: Deploy EC2 Instances
&lt;/h2&gt;

&lt;p&gt;Now for the exciting part - creating web servers! Add to &lt;code&gt;main.tf&lt;/code&gt;:&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="c1"&gt;# EC2 Instances&lt;/span&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="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance_count&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;amazon_linux&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;instance_type&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;instance_type&lt;/span&gt;
  &lt;span class="nx"&gt;key_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;key_name&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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;vpc_security_group_ids&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_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&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="nx"&gt;user_data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base64encode&lt;/span&gt;&lt;span class="p"&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
    dnf update -y
    dnf install -y httpd
    systemctl start httpd
    systemctl enable httpd
    echo "&amp;lt;h1&amp;gt;Terraform Web Server - Instance: $(ec2-metadata --instance-id | cut -d' ' -f2)&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;AZ: $(ec2-metadata --availability-zone | cut -d' ' -f2)&amp;lt;/p&amp;gt;" &amp;gt; /var/www/html/index.html
&lt;/span&gt;&lt;span class="no"&gt;    EOF
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-web-${count.index + 1}"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&lt;/span&gt;
    &lt;span class="nx"&gt;Server&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"web-${count.index + 1}"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;strong&gt;Breaking Down the Code:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Count Meta-Argument:&lt;/strong&gt;&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;count&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;instance_count&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creates multiple instances. With &lt;code&gt;instance_count = 2&lt;/code&gt;, we get 2 servers!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. User Data - The Magic:&lt;/strong&gt;&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 httpd
  # ...
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;User data runs automatically when the instance starts. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updates the system&lt;/li&gt;
&lt;li&gt;Installs Apache web server&lt;/li&gt;
&lt;li&gt;Starts Apache&lt;/li&gt;
&lt;li&gt;Creates a custom HTML page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Dynamic Naming:&lt;/strong&gt;&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;"${var.project_name}-web-${count.index + 1}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;First instance: &lt;code&gt;terraform-web-web-1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Second instance: &lt;code&gt;terraform-web-web-2&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚖️ Step 5: Create Application Load Balancer
&lt;/h2&gt;

&lt;p&gt;The load balancer distributes traffic. Add to &lt;code&gt;main.tf&lt;/code&gt;:&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="c1"&gt;# Application Load Balancer&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_lb"&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;name&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.project_name}-alb"&lt;/span&gt;
  &lt;span class="nx"&gt;internal&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="nx"&gt;load_balancer_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"application"&lt;/span&gt;
  &lt;span class="nx"&gt;security_groups&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_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alb&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="nx"&gt;subnets&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_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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="nx"&gt;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_2&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="nx"&gt;enable_deletion_protection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-alb"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Target Group&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_lb_target_group"&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;name&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.project_name}-tg"&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;80&lt;/span&gt;
  &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"HTTP"&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;health_check&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;enabled&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;healthy_threshold&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;unhealthy_threshold&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;timeout&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="nx"&gt;interval&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
    &lt;span class="nx"&gt;path&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"HTTP"&lt;/span&gt;
    &lt;span class="nx"&gt;matcher&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"200"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-tg"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Target Group Attachment&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_lb_target_group_attachment"&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;count&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;instance_count&lt;/span&gt;

  &lt;span class="nx"&gt;target_group_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_lb_target_group&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="nx"&gt;arn&lt;/span&gt;
  &lt;span class="nx"&gt;target_id&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="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="nx"&gt;index&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;port&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="c1"&gt;# ALB Listener&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_lb_listener"&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;load_balancer_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_lb&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="nx"&gt;arn&lt;/span&gt;
  &lt;span class="nx"&gt;port&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"80"&lt;/span&gt;
  &lt;span class="nx"&gt;protocol&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"HTTP"&lt;/span&gt;

  &lt;span class="nx"&gt;default_action&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="s2"&gt;"forward"&lt;/span&gt;
    &lt;span class="nx"&gt;target_group_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_lb_target_group&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="nx"&gt;arn&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-listener"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&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.amazonaws.com%2Fuploads%2Farticles%2Ffccbk1qksgt48fu3fh3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffccbk1qksgt48fu3fh3w.png" alt=" " width="798" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding Load Balancer Components:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Application Load Balancer (ALB):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The main load balancer resource&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;internal = false&lt;/code&gt; - Internet-facing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;load_balancer_type = "application"&lt;/code&gt; - Layer 7 (HTTP/HTTPS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Target Group:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manages the backend servers&lt;/li&gt;
&lt;li&gt;Performs health checks every 30 seconds&lt;/li&gt;
&lt;li&gt;Marks servers healthy after 2 successful checks&lt;/li&gt;
&lt;li&gt;Marks servers unhealthy after 2 failed checks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Target Group Attachment:&lt;/strong&gt;&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;count&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;instance_count&lt;/span&gt;
&lt;span class="nx"&gt;target_id&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&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="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&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;Registers each EC2 instance with the target group.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Listener:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Listens on port 80&lt;/li&gt;
&lt;li&gt;Forwards traffic to the target group&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Health Check Flow:&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;ALB → Checks "/" every 30s → Expects HTTP 200 → 
  ✅ Healthy (2 successes) → Receives traffic
  ❌ Unhealthy (2 failures) → No traffic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📤 Step 6: Define Outputs
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;outputs.tf&lt;/code&gt;:&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="c1"&gt;# VPC Outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"vpc_id"&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;"ID of the VPC"&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;aws_vpc&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="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Subnet Output&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"public_subnet_id"&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;"ID of public subnet"&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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="c1"&gt;# EC2 Instance Outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_ids"&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;"IDs of EC2 instances"&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;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="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="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_public_ips"&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;"Public IPs of EC2 instances"&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;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="p"&gt;[*].&lt;/span&gt;&lt;span class="nx"&gt;public_ip&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Load Balancer Outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"alb_dns_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;"DNS name of the Application Load Balancer"&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;aws_lb&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="nx"&gt;dns_name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"alb_url"&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;"URL to access the load balancer"&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://${aws_lb.main.dns_name}"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Security Group Outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"alb_security_group_id"&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;"ID of ALB security group"&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;aws_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alb&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="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_security_group_id"&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;"ID of instance security group"&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;aws_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&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;/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.amazonaws.com%2Fuploads%2Farticles%2Fqh3c9hhayj81ajiboh38.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqh3c9hhayj81ajiboh38.png" alt=" " width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Splat Expression:&lt;/strong&gt;&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;aws_instance&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web&lt;/span&gt;&lt;span class="p"&gt;[*]&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;The &lt;code&gt;[*]&lt;/code&gt; gets ALL instance IDs as a list. Super useful with &lt;code&gt;count&lt;/code&gt;!&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Step 7: Set Variable Values
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;terraform.tfvars&lt;/code&gt;:&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;aws_region&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="nx"&gt;project_name&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-web"&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;"dev"&lt;/span&gt;

&lt;span class="c1"&gt;# Network Configuration&lt;/span&gt;
&lt;span class="nx"&gt;vpc_cidr&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;
&lt;span class="nx"&gt;public_subnet_cidr&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.1.0/24"&lt;/span&gt;

&lt;span class="c1"&gt;# EC2 Configuration&lt;/span&gt;
&lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;
&lt;span class="nx"&gt;instance_count&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="nx"&gt;key_name&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-key"&lt;/span&gt;

&lt;span class="c1"&gt;# Security - Change this to your IP address&lt;/span&gt;
&lt;span class="nx"&gt;my_ip&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.0.0.0/0"&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.amazonaws.com%2Fuploads%2Farticles%2Faneab1a2uyh07iikqkvj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faneab1a2uyh07iikqkvj.png" alt=" " width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Important:&lt;/strong&gt; Change &lt;code&gt;my_ip&lt;/code&gt; to your actual IP address for security!&lt;/p&gt;

&lt;p&gt;Find your IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl ifconfig.me
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update:&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;my_ip&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"203.0.113.0/32"&lt;/span&gt;  &lt;span class="c1"&gt;# Your IP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 Step 8: Deploy the Infrastructure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Create SSH Key Pair (if you don't have one)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create key pair in AWS&lt;/span&gt;
aws ec2 create-key-pair &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--key-name&lt;/span&gt; my-key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'KeyMaterial'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; my-key.pem

&lt;span class="o"&gt;![&lt;/span&gt; &lt;span class="o"&gt;](&lt;/span&gt;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ttadkcyqnuxbsnpwdqs7.png&lt;span class="o"&gt;)&lt;/span&gt;


&lt;span class="c"&gt;# Set permissions&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;400 my-key.pem
&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.amazonaws.com%2Fuploads%2Farticles%2F5w5onxtbivy5i7f6eju6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5w5onxtbivy5i7f6eju6.png" alt=" " width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Initialize Terraform
&lt;/h3&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;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Initializing the backend...
Initializing provider plugins...
&lt;/span&gt;&lt;span class="gp"&gt;- Finding hashicorp/aws versions matching "~&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;5.0&lt;span class="s2"&gt;"...
&lt;/span&gt;&lt;span class="go"&gt;- Installing hashicorp/aws v5.100.0...

Terraform has been successfully initialized!
&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.amazonaws.com%2Fuploads%2Farticles%2Fcugi4ubz4be7o44aclr5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcugi4ubz4be7o44aclr5.png" alt=" " width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Review the Plan
&lt;/h3&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;You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan: 14 to add, 0 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resources being created:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 VPC&lt;/li&gt;
&lt;li&gt;1 Internet Gateway&lt;/li&gt;
&lt;li&gt;1 Subnet&lt;/li&gt;
&lt;li&gt;1 Route Table + Association&lt;/li&gt;
&lt;li&gt;2 Security Groups&lt;/li&gt;
&lt;li&gt;2 EC2 Instances&lt;/li&gt;
&lt;li&gt;1 Application Load Balancer&lt;/li&gt;
&lt;li&gt;1 Target Group&lt;/li&gt;
&lt;li&gt;2 Target Group Attachments&lt;/li&gt;
&lt;li&gt;1 ALB Listener&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  4. Apply the Configuration
&lt;/h3&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;Type &lt;code&gt;yes&lt;/code&gt; when prompted.&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%2F2ylek3n7tulgcoz3pwbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ylek3n7tulgcoz3pwbg.png" alt=" " width="778" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This will take 3-5 minutes&lt;/strong&gt; because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 instances need to boot&lt;/li&gt;
&lt;li&gt;User data script runs&lt;/li&gt;
&lt;li&gt;ALB needs to provision&lt;/li&gt;
&lt;li&gt;Health checks need to pass&lt;/li&gt;
&lt;/ul&gt;

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




&lt;h2&gt;
  
  
  ✅ Step 9: Test Your Infrastructure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Get the Load Balancer URL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform output alb_url
&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://terraform-web-alb-1740709428.us-east-1.elb.amazonaws.com
&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.amazonaws.com%2Fuploads%2Farticles%2Fxmtznr2i4okd2xizw9cc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmtznr2i4okd2xizw9cc.png" alt=" " width="800" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Test in Browser
&lt;/h3&gt;

&lt;p&gt;Open the URL in your browser. You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🚀 Terraform Web Server
Deployed with Infrastructure as Code

Instance ID: i-09305fc7d4638360a
Availability Zone: us-east-1a
Server: 1
&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.amazonaws.com%2Fuploads%2Farticles%2Fakpjfa84z1su2uavux4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakpjfa84z1su2uavux4a.png" alt=" " width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Test Load Balancing
&lt;/h3&gt;

&lt;p&gt;Refresh the page multiple times. You'll see the &lt;strong&gt;Instance ID&lt;/strong&gt; and &lt;strong&gt;Server number&lt;/strong&gt; change - that's the load balancer distributing traffic!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;First request  → Server: 1
Second request → Server: 2
Third request  → Server: 1
&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.amazonaws.com%2Fuploads%2Farticles%2F8xsbgk7ketma91mhrisf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xsbgk7ketma91mhrisf.png" alt=" " width="800" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Test Individual Instances
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get instance IPs&lt;/span&gt;
terraform output instance_public_ips

&lt;span class="o"&gt;![&lt;/span&gt; &lt;span class="o"&gt;](&lt;/span&gt;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbibepofm64vdjwyk9kj.png&lt;span class="o"&gt;)&lt;/span&gt;


&lt;span class="c"&gt;# Test directly (should work)&lt;/span&gt;
curl http://&amp;lt;instance-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔍 Understanding What Happened
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Traffic Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
    ↓
ALB DNS (terraform-web-alb-xxx.elb.amazonaws.com)
    ↓
ALB Listener (Port 80)
    ↓
Target Group (Health Check: ✅)
    ↓
Round-Robin Distribution
    ├─→ EC2 Instance 1 (Apache) → Response
    └─→ EC2 Instance 2 (Apache) → Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Health Check Process
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Every 30 seconds:
ALB → GET / → EC2 Instance
    ↓
HTTP 200 OK?
    ├─ Yes (2 times) → Mark Healthy → Send Traffic
    └─ No (2 times)  → Mark Unhealthy → Stop Traffic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Advanced Testing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Test High Availability
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; What if one server fails?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get instance IDs&lt;/span&gt;
terraform output instance_ids

&lt;span class="c"&gt;# Stop one instance&lt;/span&gt;
aws ec2 stop-instances &lt;span class="nt"&gt;--instance-ids&lt;/span&gt; i-xxxxx

&lt;span class="c"&gt;# Wait 1 minute for health check to fail&lt;/span&gt;

&lt;span class="c"&gt;# Test the ALB URL - still works!&lt;/span&gt;
curl http://&amp;lt;alb-dns&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ALB automatically stops sending traffic to the unhealthy instance!&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitor Health Status
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check target health&lt;/span&gt;
aws elbv2 describe-target-health &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-group-arn&lt;/span&gt; &amp;lt;target-group-arn&amp;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 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;"TargetHealthDescriptions"&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Target"&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;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"i-xxxxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&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;span class="nl"&gt;"HealthCheckPort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"80"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"TargetHealth"&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;span class="nl"&gt;"State"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"healthy"&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;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;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;h2&gt;
  
  
  🐛 Troubleshooting Common Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: "InvalidKeyPair.NotFound"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&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;Error: creating EC2 Instance: InvalidKeyPair.NotFound
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List your key pairs&lt;/span&gt;
aws ec2 describe-key-pairs

&lt;span class="c"&gt;# Create if missing&lt;/span&gt;
aws ec2 create-key-pair &lt;span class="nt"&gt;--key-name&lt;/span&gt; my-key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'KeyMaterial'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; my-key.pem
&lt;span class="nb"&gt;chmod &lt;/span&gt;400 my-key.pem

&lt;span class="c"&gt;# Update terraform.tfvars with correct key name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue 2: ALB Shows "503 Service Unavailable"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Instances are unhealthy or still booting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Wait 2-3 minutes for:&lt;/span&gt;
&lt;span class="c"&gt;# 1. Instances to boot&lt;/span&gt;
&lt;span class="c"&gt;# 2. User data to complete&lt;/span&gt;
&lt;span class="c"&gt;# 3. Health checks to pass&lt;/span&gt;

&lt;span class="c"&gt;# Check target health&lt;/span&gt;
aws elbv2 describe-target-health &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-group-arn&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;terraform output &lt;span class="nt"&gt;-raw&lt;/span&gt; target_group_arn&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue 3: Can't SSH to Instances
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Security group blocks your IP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get your current IP&lt;/span&gt;
curl ifconfig.me

&lt;span class="c"&gt;# Update terraform.tfvars&lt;/span&gt;
my_ip &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"YOUR_IP/32"&lt;/span&gt;

&lt;span class="c"&gt;# Apply changes&lt;/span&gt;
terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue 4: "Subnet must have at least 2 availability zones"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error with ALB:&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;Error: creating ELBv2 Load Balancer: ValidationError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; ALBs require at least 2 subnets in different AZs. Update &lt;code&gt;main.tf&lt;/code&gt;:&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="c1"&gt;# Add second subnet&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"public_2"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&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.2.0/24"&lt;/span&gt;
  &lt;span class="nx"&gt;availability_zone&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_availability_zones&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;map_public_ip_on_launch&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;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-public-subnet-2"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Update ALB subnets&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_lb"&lt;/span&gt; &lt;span class="s2"&gt;"main"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="nx"&gt;subnets&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_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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="nx"&gt;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_2&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💰 Cost Breakdown
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Monthly Costs (us-east-1):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;Cost/Month&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;t2.micro EC2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;$8.50&lt;/td&gt;
&lt;td&gt;$17.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application Load Balancer&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$16.20&lt;/td&gt;
&lt;td&gt;$16.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Transfer (1GB)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;$0.09&lt;/td&gt;
&lt;td&gt;$0.09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$33.29&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Free Tier Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First 750 hours/month of t2.micro (covers both instances!)&lt;/li&gt;
&lt;li&gt;First 15 GB data transfer out&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actual cost with free tier: ~$16.20/month&lt;/strong&gt; (just the ALB)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost Optimization Tips:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use t2.micro (free tier eligible)&lt;/li&gt;
&lt;li&gt;Delete resources when not in use&lt;/li&gt;
&lt;li&gt;Use Network Load Balancer ($10.95/month) if you don't need Layer 7 features&lt;/li&gt;
&lt;li&gt;Consider using Auto Scaling (covered in future articles)&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🧹 Cleanup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Don't forget to destroy resources to avoid charges!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Destroy everything&lt;/span&gt;
terraform destroy

&lt;span class="c"&gt;# Type 'yes' when prompted&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.amazonaws.com%2Fuploads%2Farticles%2Fgwb740r1s3n1coq8826s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgwb740r1s3n1coq8826s.png" alt=" " width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will delete:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Load Balancer&lt;/li&gt;
&lt;li&gt;✅ Target Group&lt;/li&gt;
&lt;li&gt;✅ EC2 Instances&lt;/li&gt;
&lt;li&gt;✅ Security Groups&lt;/li&gt;
&lt;li&gt;✅ VPC and networking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verify deletion:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check EC2 instances&lt;/span&gt;
aws ec2 describe-instances &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=tag:ManagedBy,Values=Terraform"&lt;/span&gt;

&lt;span class="c"&gt;# Check load balancers&lt;/span&gt;
aws elbv2 describe-load-balancers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📚 Key Concepts Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Count Meta-Argument&lt;/strong&gt;
&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;count&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creates multiple identical resources. Access with &lt;code&gt;[count.index]&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Data Sources&lt;/strong&gt;
&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;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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Query existing AWS resources instead of hardcoding values.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;User Data&lt;/strong&gt;
&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;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
  # Bootstrap script
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Automate instance configuration at launch.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Security Group References&lt;/strong&gt;
&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;security_groups&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alb&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reference one security group from another for layered security.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Splat Expressions&lt;/strong&gt;
&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;aws_instance&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web&lt;/span&gt;&lt;span class="p"&gt;[*]&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;Get all values from resources created with &lt;code&gt;count&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Health Checks&lt;/strong&gt;
&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;health_check&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;path&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;
  &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Automatic monitoring and traffic routing.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Real-World Applications
&lt;/h2&gt;

&lt;p&gt;This architecture is used for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Web Applications&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WordPress sites&lt;/li&gt;
&lt;li&gt;E-commerce platforms&lt;/li&gt;
&lt;li&gt;SaaS applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. API Backends&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REST APIs&lt;/li&gt;
&lt;li&gt;GraphQL servers&lt;/li&gt;
&lt;li&gt;Microservices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Content Delivery&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static websites&lt;/li&gt;
&lt;li&gt;Media streaming&lt;/li&gt;
&lt;li&gt;File downloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Development Environments&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Staging servers&lt;/li&gt;
&lt;li&gt;Testing environments&lt;/li&gt;
&lt;li&gt;Demo applications&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 What's Next?
&lt;/h2&gt;

&lt;p&gt;In the next article, we'll add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RDS Database&lt;/strong&gt; - Persistent data storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Secrets Manager&lt;/strong&gt; - Secure credential management&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private Subnets&lt;/strong&gt; - Enhanced security&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Connection&lt;/strong&gt; - Connect EC2 to RDS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Coming Up:&lt;/strong&gt; &lt;a href="https://dev.tolink"&gt;Article 8: Secure Database Deployment: RDS + Secrets Manager with Terraform&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📖 Additional Resources
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Official Documentation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance" rel="noopener noreferrer"&gt;Terraform AWS Provider - EC2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb" rel="noopener noreferrer"&gt;Terraform AWS Provider - ALB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/" rel="noopener noreferrer"&gt;AWS Application Load Balancer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Related Articles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.tolink"&gt;Article 6: Building Your First AWS VPC with Terraform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tolink"&gt;Article 5: Variables and Outputs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/architecture/well-architected/" rel="noopener noreferrer"&gt;AWS Well-Architected Framework&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Questions?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Common Questions:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I use different instance types for each server?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A: Yes! Use &lt;code&gt;for_each&lt;/code&gt; instead of &lt;code&gt;count&lt;/code&gt; for more flexibility (covered in Article 13).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do I add HTTPS/SSL?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A: You'll need an ACM certificate and update the listener to port 443. We'll cover this in a future article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I deploy to multiple regions?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A: Yes! Use Terraform workspaces or separate state files per region.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do I add auto-scaling?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A: Replace EC2 instances with an Auto Scaling Group. We'll cover this in Article 15.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Summary
&lt;/h2&gt;

&lt;p&gt;Today you learned how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Deploy multiple EC2 instances with Terraform&lt;/li&gt;
&lt;li&gt;✅ Use &lt;code&gt;count&lt;/code&gt; to create multiple resources&lt;/li&gt;
&lt;li&gt;✅ Configure security groups for layered security&lt;/li&gt;
&lt;li&gt;✅ Automate server setup with user data&lt;/li&gt;
&lt;li&gt;✅ Create an Application Load Balancer&lt;/li&gt;
&lt;li&gt;✅ Implement health checks and high availability&lt;/li&gt;
&lt;li&gt;✅ Test load balancing in action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You now have production-ready web infrastructure!&lt;/strong&gt; 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading. I hope this article provided practical insights and a clearer understanding of the topic.&lt;/p&gt;

&lt;p&gt;If you found this useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value
&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today
&lt;/li&gt;
&lt;li&gt;💾 Save it for your next optimization session
&lt;/li&gt;
&lt;li&gt;🔄 Share it with your team
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives are coming soon on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Operations&lt;/li&gt;
&lt;li&gt;GenAI &amp;amp; Agentic AI&lt;/li&gt;
&lt;li&gt;DevOps Automation&lt;/li&gt;
&lt;li&gt;Data &amp;amp; Platform Engineering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow along for weekly insights and hands-on guides.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts. Feel free to drop a comment or connect with me on:&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, reach out at:&lt;/p&gt;

&lt;p&gt;📧 &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Found this helpful? Share it with your team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⭐ Star the repo • 📖 Follow the series • 💬 Ask questions  &lt;/p&gt;

&lt;p&gt;Made by &lt;strong&gt;Sarvar Nadaf&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🌐 &lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;https://sarvarnadaf.com&lt;/a&gt;&lt;/p&gt;




</description>
      <category>terraform</category>
      <category>devops</category>
      <category>aws</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Stop Giving AI Agents AWS Credentials: A Better Way to Secure Access</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Mon, 20 Apr 2026 14:00:16 +0000</pubDate>
      <link>https://forem.com/aws-builders/stop-giving-ai-agents-aws-credentials-a-better-way-to-secure-access-5gih</link>
      <guid>https://forem.com/aws-builders/stop-giving-ai-agents-aws-credentials-a-better-way-to-secure-access-5gih</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;

&lt;p&gt;Let's dive in and explore the fascinating world of cloud technology together! 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  The Wake-Up Call
&lt;/h2&gt;

&lt;p&gt;Three months ago, our security team flagged something concerning. Developers were feeding production logs, error messages, and configuration snippets to ChatGPT for debugging help.&lt;/p&gt;

&lt;p&gt;The problem? Those logs contained customer identifiers, internal service names, and architectural details we definitely didn't want leaving our network.&lt;/p&gt;

&lt;p&gt;We couldn't just block ChatGPT - developers needed AI assistance. The productivity gains were real. But we also couldn't keep hemorrhaging sensitive data to external APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The requirements were clear:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI agents need AWS access for legitimate automation tasks&lt;/li&gt;
&lt;li&gt;Zero sensitive data leaves our AWS environment&lt;/li&gt;
&lt;li&gt;Every action must be auditable&lt;/li&gt;
&lt;li&gt;Principle of least privilege, always&lt;/li&gt;
&lt;li&gt;No impact on developer velocity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's when I started looking at Model Context Protocol (MCP) as a security boundary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding MCP as a Security Layer
&lt;/h2&gt;

&lt;p&gt;Before diving into implementation, let's clarify what MCP actually does and why it matters for security.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model Context Protocol&lt;/strong&gt; is an open standard that sits between your AI agent and your resources. Think of it as a translator and gatekeeper combined.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer → AI Agent → MCP Server → AWS IAM → AWS Resources
                          ↓
                    Security Layer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The MCP server doesn't just pass requests through. It acts as a security boundary that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validates every request before execution&lt;/li&gt;
&lt;li&gt;Translates AI intentions into specific AWS API calls&lt;/li&gt;
&lt;li&gt;Enforces authentication and authorization&lt;/li&gt;
&lt;li&gt;Logs everything for audit trails&lt;/li&gt;
&lt;li&gt;Provides a single point of control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Instead of giving AI agents direct AWS credentials, you give them access to an MCP server that has carefully scoped permissions. The AI never touches AWS credentials. It doesn't even know they exist.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Security Architecture
&lt;/h2&gt;

&lt;p&gt;After several iterations, here's the pattern that survived production. I'll explain the thinking behind each layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1: Authentication Without Permanent Credentials
&lt;/h3&gt;

&lt;p&gt;The first principle: no permanent credentials anywhere in the system.&lt;/p&gt;

&lt;p&gt;Developers authenticate with our existing identity provider (Okta in our case). The identity provider issues a JWT token containing the user's identity and group memberships. The MCP server validates this JWT and issues a short-lived session token - 15 minutes, no exceptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why 15 minutes?&lt;/strong&gt; Long enough for a debugging session, short enough that a leaked token becomes useless quickly. If someone steals a session token, they have a 15-minute window at most. Compare that to permanent AWS credentials that work forever until manually revoked.&lt;/p&gt;

&lt;p&gt;The MCP server never stores these tokens. They're validated, used, and discarded. When they expire, users re-authenticate. It's a minor inconvenience that prevents major security incidents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2: Request Validation
&lt;/h3&gt;

&lt;p&gt;This is where MCP shines as a security boundary. Every request goes through multiple validation checks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Action Allowlist:&lt;/strong&gt; The MCP server maintains a strict list of allowed AWS actions. If the AI requests something not on the list, it's blocked immediately. No wildcards, no "just in case" permissions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern Detection:&lt;/strong&gt; I scan every request for dangerous patterns. Words like "delete", "terminate", "destroy" trigger additional scrutiny. Even if the action is technically allowed, suspicious patterns can block the request or require additional approval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parameter Sanitization:&lt;/strong&gt; Before logging or processing, all sensitive parameters get redacted. Passwords, tokens, API keys - anything that looks like a credential gets replaced with &lt;code&gt;[REDACTED]&lt;/code&gt; in logs. This prevents credential leakage through audit trails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rate Limiting:&lt;/strong&gt; Each user gets a request budget. Exceed it, and requests start getting throttled. This prevents both accidental runaway scripts and intentional abuse.&lt;/p&gt;

&lt;p&gt;The validation happens in milliseconds. Developers don't notice the overhead, but it's the difference between a secure system and a disaster waiting to happen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 3: AWS Execution with Scoped Permissions
&lt;/h3&gt;

&lt;p&gt;The MCP server uses an IAM role with specific permissions. Not admin. Not power user. Just what's needed for legitimate use cases.&lt;/p&gt;

&lt;p&gt;I started by listing every legitimate use case developers had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read CloudWatch logs for debugging&lt;/li&gt;
&lt;li&gt;List S3 buckets to find data&lt;/li&gt;
&lt;li&gt;Get objects from specific buckets&lt;/li&gt;
&lt;li&gt;Query CloudWatch metrics for dashboards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I created IAM policies that allow exactly those actions and nothing else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key insight:&lt;/strong&gt; Explicit denies for dangerous actions, even if they're not in the allow list. This protects against future policy changes or misconfigurations.&lt;/p&gt;

&lt;p&gt;Example: Even if someone accidentally adds &lt;code&gt;s3:*&lt;/code&gt; to the allow list, an explicit deny on &lt;code&gt;s3:DeleteBucket&lt;/code&gt; still blocks it. Defense in depth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 4: Comprehensive Audit Trail
&lt;/h3&gt;

&lt;p&gt;CloudTrail logs every AWS API call, but it doesn't capture the context we need. Who made the request? What was the AI prompt? What resources were accessed?&lt;/p&gt;

&lt;p&gt;I built a custom logging layer that captures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User identity (email, not just IAM role)&lt;/li&gt;
&lt;li&gt;Original AI prompt (hashed, not stored in plain text)&lt;/li&gt;
&lt;li&gt;AWS action requested&lt;/li&gt;
&lt;li&gt;Resources accessed&lt;/li&gt;
&lt;li&gt;Result (success/failure)&lt;/li&gt;
&lt;li&gt;Execution time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this goes to CloudWatch Logs in structured JSON format. Now I can query: "Show me all S3 access by user X this week" or "What resources did the AI access when processing this prompt?"&lt;/p&gt;

&lt;p&gt;The logs are immutable and retained for 90 days for compliance.&lt;/p&gt;




&lt;h2&gt;
  
  
  How We Built It
&lt;/h2&gt;

&lt;p&gt;The deployment came down to three critical security decisions. Each one was driven by a specific threat we wanted to prevent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decision 1: Network Isolation Over Convenience
&lt;/h3&gt;

&lt;p&gt;I put the MCP server in a completely separate VPC from production. No shared networks, no VPC peering, nothing. The only communication path is through VPC endpoints to AWS APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; If someone compromises the MCP server, they're trapped. No internet access means they can't exfiltrate data. No production VPC access means they can't pivot to other systems. They're stuck in a cage that only opens to specific AWS services.&lt;/p&gt;

&lt;p&gt;I chose ECS Fargate because it gave me this isolation without the overhead of managing EC2 instances. No patching, no scaling configuration, just containers in a locked-down network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The trade-off:&lt;/strong&gt; More complex networking setup. But the security benefit was worth it. A compromised MCP server becomes useless to an attacker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decision 2: Explicit Denies as the Last Line of Defense
&lt;/h3&gt;

&lt;p&gt;The IAM policy has two blocks: allows and denies. The allows are specific - exact actions on exact resources. But the denies are what keep me sleeping at night.&lt;/p&gt;

&lt;p&gt;I explicitly deny all delete operations, all terminate operations, all IAM changes, and all KMS key operations. Even if someone misconfigures the allow block and adds &lt;code&gt;s3:*&lt;/code&gt;, the deny on &lt;code&gt;s3:DeleteBucket&lt;/code&gt; still holds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Policies get changed. People make mistakes. The deny block is the safety net that catches those mistakes before they become incidents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The trade-off:&lt;/strong&gt; More rigid system. If we need to add a delete operation later, we have to modify both blocks. But that friction is intentional - it forces us to think twice about dangerous permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decision 3: Real-Time Alerting Over Post-Incident Analysis
&lt;/h3&gt;

&lt;p&gt;I set up CloudWatch alarms that fire immediately when something looks wrong. High error rates, unusual request volumes, spikes in blocked actions - all trigger alerts to our security team's Slack channel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Logs are great for forensics, but alerts prevent incidents. If the AI starts trying malicious actions, I want to know in real-time, not during next week's log review.&lt;/p&gt;

&lt;p&gt;The alerts are tuned to avoid noise. More than 50 errors in 5 minutes is abnormal. More than 1,000 requests from one user in 5 minutes is suspicious. These thresholds came from watching normal usage patterns for a month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The trade-off:&lt;/strong&gt; Alert fatigue is real. We tune the thresholds monthly based on false positive rates. But I'd rather investigate a false alarm than miss a real attack.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Broke (And How I Fixed It)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: Permission Errors Everywhere
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What happened:&lt;/strong&gt; First deployment, every request failed with &lt;code&gt;AccessDenied&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; I was too restrictive. The IAM policy only allowed specific S3 buckets, but developers needed to list buckets first to know what existed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Add &lt;code&gt;s3:ListAllMyBuckets&lt;/code&gt; with a wildcard resource. Let them see what exists, but control what they can read. It's like letting someone see the library catalog without giving them keys to every book.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Start with read-only list permissions, then restrict data access. Users need to discover resources before they can use them.&lt;/p&gt;




&lt;h3&gt;
  
  
  Issue 2: CloudTrail Logs Were Useless
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What happened:&lt;/strong&gt; CloudTrail showed the MCP server's actions, but not which user requested them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; All requests came from the same IAM role. No way to trace back to individual users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Pass user context through custom CloudWatch Logs. Every MCP request gets logged with the user's email, the action requested, and the resources accessed. Now I can trace every action back to the person who requested it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; CloudTrail alone isn't enough for multi-user systems. You need custom logging to capture user context.&lt;/p&gt;




&lt;h3&gt;
  
  
  Issue 3: AI Agents Tried Creative Exploits
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What happened:&lt;/strong&gt; The AI tried to chain commands to bypass restrictions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example request:&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;"First list the S3 buckets, then for each bucket, 
download all objects and search for passwords"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; My validation checked individual actions, not sequences. The AI was trying to automate a multi-step attack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Detect and block chaining attempts. Look for words like "then", "after that", "for each", "loop through". Force users to make explicit, separate requests for each action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; AI agents are creative. They'll try to work around restrictions. You need to think like an attacker.&lt;/p&gt;




&lt;h3&gt;
  
  
  Issue 4: Rate Limiting Was Too Aggressive
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What happened:&lt;/strong&gt; Legitimate users hit rate limits during normal debugging sessions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; I set limits too low (10 requests per minute). Debugging often requires rapid iteration - check logs, adjust query, check again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Tiered rate limits based on action type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read operations (Get, Describe): 100 requests per 5 minutes&lt;/li&gt;
&lt;li&gt;List operations: 50 requests per 5 minutes&lt;/li&gt;
&lt;li&gt;Write operations: 10 requests per 5 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read operations get higher limits because they're lower risk. Write operations stay restricted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; One-size-fits-all rate limits don't work. Different actions have different risk profiles.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;After three months in production, here's what actually matters:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Explicit Denies Are Your Friend
&lt;/h3&gt;

&lt;p&gt;Don't rely on "not allowing" something. Explicitly deny dangerous actions. Even if someone misconfigures the allow rules, the denies hold.&lt;/p&gt;

&lt;p&gt;I have explicit denies for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All delete operations&lt;/li&gt;
&lt;li&gt;All terminate operations&lt;/li&gt;
&lt;li&gt;All IAM operations&lt;/li&gt;
&lt;li&gt;All KMS key operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the "break glass" protections. They prevent catastrophic mistakes.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Log Everything, But Make It Searchable
&lt;/h3&gt;

&lt;p&gt;CloudTrail is great, but you need custom logs for MCP-specific context. I send everything to CloudWatch Logs with structured JSON.&lt;/p&gt;

&lt;p&gt;Now I can query: "Show me all S3 access by user X in the last hour" or "What resources did the AI access when processing this prompt?"&lt;/p&gt;

&lt;p&gt;The logs are immutable and retained for 90 days. If something goes wrong, I can reconstruct exactly what happened.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Sanitize Everything
&lt;/h3&gt;

&lt;p&gt;Never log the actual AI prompts. They might contain sensitive data. I hash them instead.&lt;/p&gt;

&lt;p&gt;You can still correlate requests (same hash = same prompt), but you're not storing potentially sensitive prompts in logs.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Network Isolation Matters
&lt;/h3&gt;

&lt;p&gt;The MCP server runs in a private VPC with no internet access. It can only reach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS API endpoints (via VPC endpoints)&lt;/li&gt;
&lt;li&gt;Internal authentication service&lt;/li&gt;
&lt;li&gt;CloudWatch Logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If someone compromises the MCP server, they can't exfiltrate data. They're stuck in an isolated network.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Test Your Security Controls
&lt;/h3&gt;

&lt;p&gt;I wrote tests to verify the security controls actually work. Tests like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify delete operations are blocked&lt;/li&gt;
&lt;li&gt;Verify IAM operations are blocked&lt;/li&gt;
&lt;li&gt;Verify rate limits work&lt;/li&gt;
&lt;li&gt;Verify audit logs capture user context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run these tests in CI/CD. If they pass, your security controls are working. If they fail, you know immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Alternative Approaches I Considered
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option 1: Direct IAM Roles for AI Agents
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;Simpler architecture&lt;/li&gt;
&lt;li&gt;No MCP server to maintain&lt;/li&gt;
&lt;li&gt;Lower latency&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;No request validation layer&lt;/li&gt;
&lt;li&gt;Can't block dangerous patterns&lt;/li&gt;
&lt;li&gt;Harder to audit user actions&lt;/li&gt;
&lt;li&gt;AI has direct AWS credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why I didn't use it:&lt;/strong&gt; Too risky. One prompt injection and the AI could delete production resources. The MCP layer provides defense in depth.&lt;/p&gt;




&lt;h3&gt;
  
  
  Option 2: AWS Lambda as MCP Server
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;Serverless, no infrastructure&lt;/li&gt;
&lt;li&gt;Automatic scaling&lt;/li&gt;
&lt;li&gt;Pay per request&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Cold starts (500ms+)&lt;/li&gt;
&lt;li&gt;15-minute timeout limit&lt;/li&gt;
&lt;li&gt;Harder to maintain state (rate limiting)&lt;/li&gt;
&lt;li&gt;More complex networking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why I didn't use it:&lt;/strong&gt; Cold starts killed the developer experience. Waiting 500ms for every request was frustrating. Fargate has no cold starts.&lt;/p&gt;




&lt;h3&gt;
  
  
  Option 3: API Gateway + Lambda
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;Built-in rate limiting&lt;/li&gt;
&lt;li&gt;API key management&lt;/li&gt;
&lt;li&gt;Request/response transformation&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;More complex setup&lt;/li&gt;
&lt;li&gt;Higher cost at scale&lt;/li&gt;
&lt;li&gt;Still has Lambda cold starts&lt;/li&gt;
&lt;li&gt;Overkill for internal use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why I didn't use it:&lt;/strong&gt; The built-in rate limiting was nice, but not worth the complexity for an internal tool. Fargate + ALB was simpler.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices That Actually Matter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Start With Read-Only
&lt;/h3&gt;

&lt;p&gt;Deploy with read-only permissions first. Let developers use it for a week. Then gradually add write permissions based on actual needs.&lt;/p&gt;

&lt;p&gt;This prevents over-permissioning. You'll discover what developers actually need, not what they think they need.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use Separate AWS Accounts
&lt;/h3&gt;

&lt;p&gt;Run the MCP server in a separate AWS account from your production workloads. Use cross-account roles for access.&lt;/p&gt;

&lt;p&gt;If the MCP account is compromised, production is still isolated. It's an extra layer of defense.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Monitor for Anomalies
&lt;/h3&gt;

&lt;p&gt;Set up CloudWatch alarms for unusual patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High error rates (&amp;gt;50 errors in 5 minutes)&lt;/li&gt;
&lt;li&gt;Unusual access patterns (&amp;gt;1,000 requests in 5 minutes)&lt;/li&gt;
&lt;li&gt;Blocked actions (&amp;gt;100 blocks in 5 minutes)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These alerts go to your security team. Response time is critical.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Regular Security Reviews
&lt;/h3&gt;

&lt;p&gt;Every month, review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which actions are being used most&lt;/li&gt;
&lt;li&gt;Which permissions are never used (remove them)&lt;/li&gt;
&lt;li&gt;Any blocked requests (are they legitimate needs?)&lt;/li&gt;
&lt;li&gt;Rate limit effectiveness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Security isn't set-and-forget. It requires ongoing attention.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Document Everything
&lt;/h3&gt;

&lt;p&gt;Create a runbook for common scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to add a new allowed action&lt;/li&gt;
&lt;li&gt;How to investigate suspicious activity&lt;/li&gt;
&lt;li&gt;How to rotate credentials&lt;/li&gt;
&lt;li&gt;How to handle a security incident&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When something goes wrong at 2 AM, you'll be glad you documented it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Three months in production taught me that securing AI agent access isn't about perfect security - it's about making attacks harder than they're worth while keeping developers productive.&lt;/p&gt;

&lt;p&gt;The MCP pattern works because it gives you a single point of control. You're not trying to secure the AI agent itself. You're securing the gateway it uses to access your resources. That gateway validates every request, enforces least privilege, logs everything, and runs in an isolated network.&lt;/p&gt;

&lt;p&gt;We went from developers sending production data to ChatGPT to having a secure, auditable system where AI agents help without creating risk. The benefit? No more 2 AM calls about data leaks.&lt;/p&gt;

&lt;p&gt;Is it perfect? No. Can a determined attacker find ways around it? Probably. But it's dramatically better than the alternatives: giving AI agents direct AWS credentials or blocking AI tools entirely and watching developers find workarounds.&lt;/p&gt;

&lt;p&gt;The key insight: Security is not about building walls. It's about building gates with guards. MCP is that gate.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Security is not about building walls. It's about building gates with guards."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading! I hope this gave you practical ideas for securing AI agent access in your environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Found this useful?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it helped you think through your security approach&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you're implementing this pattern&lt;/li&gt;
&lt;li&gt;💾 Save for your next security review&lt;/li&gt;
&lt;li&gt;🔄 Share with your security team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Follow me for more on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS security patterns&lt;/li&gt;
&lt;li&gt;AI/ML infrastructure&lt;/li&gt;
&lt;li&gt;Cloud architecture&lt;/li&gt;
&lt;li&gt;DevSecOps practices&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What's Next
&lt;/h2&gt;

&lt;p&gt;I'm working on a follow-up article about monitoring and alerting for MCP deployments. Follow for updates.&lt;/p&gt;

&lt;p&gt;Also exploring: Multi-region MCP deployments and disaster recovery patterns.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;Explore my full body of work, certifications, and architecture projects:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;Looking for hands-on guidance with cloud security or AI infrastructure?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Security Architecture (AWS / Azure)&lt;/li&gt;
&lt;li&gt;AI/ML Infrastructure Design&lt;/li&gt;
&lt;li&gt;Security Audit &amp;amp; Remediation&lt;/li&gt;
&lt;li&gt;Technical Writing &amp;amp; Documentation&lt;/li&gt;
&lt;li&gt;Architecture Reviews&lt;/li&gt;
&lt;li&gt;1:1 Technical Mentorship&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let's Connect
&lt;/h2&gt;

&lt;p&gt;Questions about implementing this pattern? Drop a comment or connect with me on &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For consulting or technical discussions: &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stay secure!&lt;/strong&gt; 🔒&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>agents</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Amazon S3 Files: The Game Changer We've Been Waiting For</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Tue, 14 Apr 2026 14:09:19 +0000</pubDate>
      <link>https://forem.com/aws-builders/amazon-s3-files-the-game-changer-weve-been-waiting-for-2515</link>
      <guid>https://forem.com/aws-builders/amazon-s3-files-the-game-changer-weve-been-waiting-for-2515</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;

&lt;p&gt;Let's dive in and explore the fascinating world of cloud technology together! 🚀&lt;/p&gt;




&lt;p&gt;After working with AWS for over a decade, I've spent countless hours explaining to clients why they can't just "edit a file in S3" the way they would on their local computer. I've drawn diagrams, created analogies, and watched developers struggle with the limitations of object storage versus file systems. Well, that conversation just got a lot more interesting.&lt;/p&gt;

&lt;p&gt;In late 2025, AWS released Amazon S3 Files, and honestly, it's one of those features that makes you wonder why it took so long. Let me walk you through what it is, why it matters, and when you should (and shouldn't) use it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; S3 Files is a true POSIX-compliant file system for S3 buckets. Unlike S3 FUSE/Mountpoint, it provides full file system semantics with sub-millisecond latency. Best for: ML training, AI agents, data analytics, shared development environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem S3 Files Solves
&lt;/h2&gt;

&lt;p&gt;Let me start with a story that probably sounds familiar. Last year, I worked with a machine learning team training large language models. Their workflow looked like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Store training datasets in S3 (hundreds of gigabytes of text data)&lt;/li&gt;
&lt;li&gt;Copy datasets to an EBS volume attached to their GPU instances&lt;/li&gt;
&lt;li&gt;Train the model, saving checkpoints every hour&lt;/li&gt;
&lt;li&gt;Copy checkpoints back to S3 for durability&lt;/li&gt;
&lt;li&gt;When spot instances get interrupted, restart everything&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This workflow had several problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data duplication&lt;/strong&gt;: Paying for storage twice (S3 + EBS on every instance)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time waste&lt;/strong&gt;: 30-45 minutes copying data before training could start&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt;: Custom scripts to sync checkpoints and handle interruptions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt;: Running 2TB EBS volumes on multiple GPU instances 24/7&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spot instance pain&lt;/strong&gt;: Every interruption meant re-copying everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They tried using S3 FUSE and Mountpoint S3 to mount their S3 bucket directly, but ran into a wall. Imagine training a model for 6 hours, then having the checkpoint save fail because the training framework needs to update the checkpoint metadata a basic file operation that S3 FUSE simply can't handle. The training framework would write 95% of the checkpoint file, then fail when it tried to seek back to update the header. Why? Because S3 FUSE isn't a real file system it's just an API wrapper pretending to be one.&lt;/p&gt;

&lt;p&gt;This is exactly the problem S3 Files solves.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Exactly Is S3 Files?
&lt;/h2&gt;

&lt;p&gt;Amazon S3 Files is a true, POSIX-compliant file system that sits on top of your S3 buckets. Think of it as a high-performance bridge between your compute resources (EC2, Lambda, ECS, EKS) and your S3 data a smart caching layer that speaks both "file system" and "S3 object" fluently.&lt;/p&gt;

&lt;p&gt;Here's what makes it different from previous solutions:&lt;/p&gt;

&lt;h3&gt;
  
  
  S3 Files vs. The Old Ways
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;S3 FUSE / Mountpoint S3:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API wrappers that translate file operations into S3 API calls&lt;/li&gt;
&lt;li&gt;Limited file system semantics&lt;/li&gt;
&lt;li&gt;Can't handle operations like seeking backward in files&lt;/li&gt;
&lt;li&gt;No true concurrent write support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;S3 Files:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built on Amazon Elastic File System (EFS) technology&lt;/li&gt;
&lt;li&gt;True POSIX compliance (supports all NFS v4.1+ operations)&lt;/li&gt;
&lt;li&gt;Sub-millisecond latency for cached data&lt;/li&gt;
&lt;li&gt;Full file system semantics (create, read, update, delete, seek, append)&lt;/li&gt;
&lt;li&gt;Concurrent access from multiple compute resources&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How S3 Files Actually Works
&lt;/h2&gt;

&lt;p&gt;The architecture is clever. When you create an S3 file system and mount it to your EC2 instance, here's what happens:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Initial Mount&lt;/strong&gt;: You see your S3 bucket as a directory structure. No data is copied yet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lazy Loading&lt;/strong&gt;: When you access a file, only that file's metadata and content are loaded into a high-performance cache layer (built on EFS).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Smart Caching&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frequently accessed files stay in the cache (sub-millisecond access)&lt;/li&gt;
&lt;li&gt;Large sequential reads go directly from S3 (maximizing throughput)&lt;/li&gt;
&lt;li&gt;Only requested byte ranges are transferred (minimizing costs)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Write Operations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writes go to the cache first (fast)&lt;/li&gt;
&lt;li&gt;Changes sync back to S3 automatically within minutes&lt;/li&gt;
&lt;li&gt;You get immediate file system consistency&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bidirectional Sync&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changes in the file system appear in S3 within minutes&lt;/li&gt;
&lt;li&gt;Changes in S3 appear in the file system within seconds&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Real-World Example: AI Model Training Pipeline
&lt;/h2&gt;

&lt;p&gt;Let me show you a practical example. I recently helped an AI research team migrate their model training pipeline to use S3 Files.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Scenario
&lt;/h3&gt;

&lt;p&gt;They train large language models with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;500GB training datasets (tokenized text)&lt;/li&gt;
&lt;li&gt;Hourly checkpoint saves (10-50GB each)&lt;/li&gt;
&lt;li&gt;Multi-GPU distributed training&lt;/li&gt;
&lt;li&gt;Spot instances for cost optimization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Old Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S3 Dataset → Copy to EBS → Train Model → Save Checkpoint to EBS → Sync to S3 → Spot Interruption → Repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;30-45 minutes copying data before training starts&lt;/li&gt;
&lt;li&gt;$1,200/month in EBS costs across GPU instances&lt;/li&gt;
&lt;li&gt;Complex checkpoint sync logic&lt;/li&gt;
&lt;li&gt;Spot interruptions meant starting over with data copies&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The New Architecture with S3 Files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S3 Dataset → Mount S3 Files → Train Model → Checkpoints auto-sync to S3 → Spot Interruption → Remount &amp;amp; Resume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Results
&lt;/h3&gt;

&lt;p&gt;With S3 Files, they mount their S3 bucket directly to their GPU instances. Training frameworks like PyTorch can now write checkpoints with full file system semantics updating headers, seeking to specific positions, and appending data operations that previously failed with S3 FUSE.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Training startup&lt;/strong&gt;: Reduced from 45 minutes to 2 minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost savings&lt;/strong&gt;: $1,200/month in EBS costs eliminated&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spot instance recovery&lt;/strong&gt;: From 45 minutes to 5 minutes (just remount and resume)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified code&lt;/strong&gt;: Removed 300+ lines of checkpoint sync and recovery logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better reliability&lt;/strong&gt;: No more corrupted checkpoints or failed saves&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Use Cases Where S3 Files Shines
&lt;/h2&gt;

&lt;p&gt;Now that you understand how it works, let's look at where S3 Files makes the biggest impact.&lt;/p&gt;

&lt;p&gt;Based on my experience and conversations with other architects, here are the scenarios where S3 Files is a perfect fit:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Machine Learning Training
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: Training models on large datasets stored in S3&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before S3 Files&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy entire dataset to EBS/EFS before training&lt;/li&gt;
&lt;li&gt;Wait hours for data transfer&lt;/li&gt;
&lt;li&gt;Pay for duplicate storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;With S3 Files&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mount S3 bucket directly&lt;/li&gt;
&lt;li&gt;Training starts immediately (lazy loading)&lt;/li&gt;
&lt;li&gt;Only accessed data is cached&lt;/li&gt;
&lt;li&gt;Multiple training instances can share the same data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. AI Agents and Automation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: AI agents using Python libraries and CLI tools that expect file systems&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Challenge&lt;/strong&gt;: Many AI agents and automation tools are built with traditional file system operations in mind. Rewriting them to use S3 APIs directly would require significant code changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With S3 Files&lt;/strong&gt;: Your existing code that expects file system access works without modification. The agent can read, write, and process files as if they were on a local file system, while S3 Files handles the synchronization with your S3 bucket automatically.&lt;/p&gt;

&lt;p&gt;This means AI agents can use standard Python libraries, shell scripts, and CLI tools without any code changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Shared Development Environments
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: Multiple developers or containers need concurrent access to shared data&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With S3 Files&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mount the same S3 bucket on multiple EC2 instances&lt;/li&gt;
&lt;li&gt;Developers can read and write simultaneously&lt;/li&gt;
&lt;li&gt;Changes are visible across all instances within seconds&lt;/li&gt;
&lt;li&gt;No complex locking mechanisms needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially powerful for Kubernetes clusters where pods need shared access to training data or model artifacts across nodes.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Content Management Systems
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: CMS storing media files that need to be accessed by multiple web servers&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With S3 Files&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All web servers mount the same S3 bucket&lt;/li&gt;
&lt;li&gt;Upload once, available everywhere immediately&lt;/li&gt;
&lt;li&gt;No need for S3 sync scripts or CDN invalidation delays&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Important Considerations
&lt;/h2&gt;

&lt;p&gt;Let me share some lessons learned from real implementations:&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance Characteristics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First access&lt;/strong&gt;: Slower (loading from S3 to cache)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subsequent access&lt;/strong&gt;: Sub-millisecond (from cache)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large sequential reads&lt;/strong&gt;: Served directly from S3 (high throughput)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small random reads&lt;/strong&gt;: Served from cache (low latency)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: If you know which files you'll need, you can pre-load them into the cache to avoid first-access latency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consistency Model
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;File system to S3&lt;/strong&gt;: Changes appear in S3 within minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3 to file system&lt;/strong&gt;: Changes appear in file system within seconds (sometimes up to a minute)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: If you need immediate consistency, use the file system as your source of truth during processing, then let it sync to S3.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost Structure
&lt;/h3&gt;

&lt;p&gt;S3 Files has three cost components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Storage&lt;/strong&gt;: $0.30/GB-month for data in the cache&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data access&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;$0.03/GB for reads&lt;/li&gt;
&lt;li&gt;$0.06/GB for writes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3 costs&lt;/strong&gt;: Standard S3 storage and request costs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Cost optimization tip&lt;/strong&gt;: The cache only stores actively used data. If you're processing 100GB from a 10TB bucket, you only pay cache costs for the 100GB.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encryption in transit&lt;/strong&gt;: TLS 1.3 (automatic)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encryption at rest&lt;/strong&gt;: SSE-S3 or KMS (your choice)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access control&lt;/strong&gt;: IAM policies + POSIX permissions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network isolation&lt;/strong&gt;: Mount targets live in your VPC&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When NOT to Use S3 Files
&lt;/h2&gt;

&lt;p&gt;Being honest about limitations is important. S3 Files isn't the right choice for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simple object storage&lt;/strong&gt;: If you're just storing and retrieving whole objects, regular S3 is simpler and cheaper.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Infrequent access&lt;/strong&gt;: If you rarely access your data, the cache storage costs aren't worth it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windows-specific features&lt;/strong&gt;: If you need Windows file system features, use FSx for Windows File Server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Extreme performance HPC&lt;/strong&gt;: If you need the absolute highest performance for HPC workloads, FSx for Lustre is better optimized.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;On-premises integration&lt;/strong&gt;: If you're migrating from on-prem NAS, FSx for NetApp ONTAP provides better compatibility.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;S3 Files is available in all commercial AWS regions as of April 2026. You can create an S3 file system through the AWS Console, AWS CLI, or infrastructure as code tools like CloudFormation and Terraform.&lt;/p&gt;

&lt;p&gt;The basic workflow involves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating an S3 file system linked to your bucket&lt;/li&gt;
&lt;li&gt;Configuring network access (VPC, subnets, security groups)&lt;/li&gt;
&lt;li&gt;Setting up IAM permissions&lt;/li&gt;
&lt;li&gt;Mounting the file system on your compute resources&lt;/li&gt;
&lt;li&gt;Using standard file operations to interact with your S3 data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;In the next article, I'll walk you through a complete hands-on implementation with step-by-step commands and real examples.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  My Take After Using It
&lt;/h2&gt;

&lt;p&gt;I've been working with S3 Files since early access in late 2025, across several client projects. Here's my honest assessment:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I love:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It eliminates entire categories of data movement code&lt;/li&gt;
&lt;li&gt;Applications that expect file systems just work&lt;/li&gt;
&lt;li&gt;The lazy loading is genuinely smart&lt;/li&gt;
&lt;li&gt;Cost savings are real when you eliminate data duplication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What to watch out for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The sync delay (minutes) can surprise people expecting instant S3 updates&lt;/li&gt;
&lt;li&gt;You need to understand the caching behavior to optimize costs&lt;/li&gt;
&lt;li&gt;Security group configuration is an extra step that trips people up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bottom line&lt;/strong&gt;: If you're currently copying data between S3 and file systems, or if you're struggling with S3 FUSE limitations, S3 Files is absolutely worth evaluating. It's not a silver bullet, but for the right use cases, it's transformative.&lt;/p&gt;




&lt;h2&gt;
  
  
  Availability and Pricing
&lt;/h2&gt;

&lt;p&gt;As of April 2026, S3 Files is available in all commercial AWS regions.&lt;/p&gt;

&lt;p&gt;Pricing varies by region, but in us-east-1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache storage: $0.30/GB-month&lt;/li&gt;
&lt;li&gt;Read operations: $0.03/GB&lt;/li&gt;
&lt;li&gt;Write operations: $0.06/GB&lt;/li&gt;
&lt;li&gt;Plus standard S3 costs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check the &lt;a href="https://aws.amazon.com/s3/pricing/" rel="noopener noreferrer"&gt;S3 pricing page&lt;/a&gt; for your region's specific pricing.&lt;/p&gt;




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

&lt;p&gt;Amazon S3 Files represents a significant shift in how we can architect cloud applications. For years, we've had to choose between S3's durability and cost-effectiveness versus a file system's interactive capabilities. S3 Files eliminates that tradeoff.&lt;/p&gt;

&lt;p&gt;Whether you're training ML models on spot instances, building AI agents, running data analytics pipelines, or any workload that needs shared, interactive file access to S3 data, S3 Files deserves a serious look. It's not just a new feature it's a new way of thinking about data access in the cloud.&lt;/p&gt;

&lt;p&gt;The best part? You don't need to rewrite your applications. If your code works with files, it'll work with S3 Files. And that's the kind of simplicity we all need more of in cloud architecture.&lt;/p&gt;

&lt;p&gt;In my next article, I'll show you exactly how to set up S3 Files with a complete hands-on implementation guide, including all the commands, configurations, and real-world testing scenarios.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you tried S3 Files yet? I'd love to hear about your use cases and experiences. The cloud architecture community learns best when we share real-world implementations, not just theory.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading! I hope this article gave you practical insights and a clearer perspective on the topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Was this helpful?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today&lt;/li&gt;
&lt;li&gt;💾 Save for your next optimization session&lt;/li&gt;
&lt;li&gt;🔄 Share with your team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Follow me for more on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS architecture patterns&lt;/li&gt;
&lt;li&gt;FinOps automation&lt;/li&gt;
&lt;li&gt;Multi-account strategies&lt;/li&gt;
&lt;li&gt;AI-driven DevOps&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives coming soon on cloud operations, GenAI, Agentic-AI, DevOps, and data workflows follow for weekly insights.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts drop a comment or connect with me on &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, feel free to reach out directly at &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Learning&lt;/strong&gt; 🚀&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>cloud</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Building Your First VPC: AWS Networking with Terraform</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Wed, 08 Apr 2026 10:04:44 +0000</pubDate>
      <link>https://forem.com/aws-builders/building-your-first-vpc-aws-networking-with-terraform-3h34</link>
      <guid>https://forem.com/aws-builders/building-your-first-vpc-aws-networking-with-terraform-3h34</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Welcome Back!
&lt;/h2&gt;

&lt;p&gt;Remember in &lt;a href="https://dev.to/aws-builders/terraform-variables-and-outputs-making-your-infrastructure-flexible-3ebc"&gt;Article 5&lt;/a&gt; when you learned about variables and outputs? You created flexible, reusable S3 bucket configurations. That's great for storage, but what about &lt;strong&gt;networking&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the reality:&lt;/strong&gt; S3 buckets are public services. But what about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 instances that need network isolation?&lt;/li&gt;
&lt;li&gt;Databases that should never be directly accessible from the internet?&lt;/li&gt;
&lt;li&gt;Applications that need both public and private components?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;That's where VPC (Virtual Private Cloud) comes in.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the end of this article, you'll:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Understand VPC fundamentals (CIDR, subnets, routing)&lt;/li&gt;
&lt;li&gt;✅ Create a production-ready VPC with Terraform&lt;/li&gt;
&lt;li&gt;✅ Configure public and private subnets&lt;/li&gt;
&lt;li&gt;✅ Set up Internet Gateway and NAT Gateway&lt;/li&gt;
&lt;li&gt;✅ Master route tables and associations&lt;/li&gt;
&lt;li&gt;✅ Use data sources to fetch AWS information&lt;/li&gt;
&lt;li&gt;✅ Build cost-optimized VPC architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time Required:&lt;/strong&gt; 45 minutes (20 min read + 25 min practice)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; ~$0.05 for testing (destroy immediately!)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Difficulty:&lt;/strong&gt; Intermediate&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚠️ IMPORTANT:&lt;/strong&gt; NAT Gateway costs $0.045/hour (~$32/month). We'll create it for learning, but &lt;strong&gt;destroy it immediately&lt;/strong&gt; after testing!&lt;/p&gt;

&lt;p&gt;Let's build real infrastructure! 🚀&lt;/p&gt;


&lt;h2&gt;
  
  
  💔 The Problem: Networking Confusion
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Manual Nightmare
&lt;/h3&gt;

&lt;p&gt;Imagine this scenario (maybe you've lived it):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your Task:&lt;/strong&gt; "Set up a VPC for our new application"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You open AWS Console:&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;Step 1: Create VPC... wait, what's a CIDR block?
Step 2: Create subnets... public or private? What's the difference?
Step 3: Internet Gateway... where does this go?
Step 4: NAT Gateway... why do I need this?
Step 5: Route tables... which subnet goes where?
Step 6: *2 hours later* ... did I configure this correctly?
Step 7: *Application doesn't work* ... something's wrong with routing
Step 8: *Starts over* 😰
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common Problems:
&lt;/h3&gt;

&lt;p&gt;❌ &lt;strong&gt;Forgot route table associations&lt;/strong&gt; - Subnets can't reach internet&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Wrong CIDR blocks&lt;/strong&gt; - IP addresses overlap&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;NAT Gateway in wrong subnet&lt;/strong&gt; - Private instances can't update&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Inconsistent configuration&lt;/strong&gt; - Resources don't work together&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Can't remember configuration&lt;/strong&gt; - No documentation&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Takes hours to set up&lt;/strong&gt; - Clicking through endless screens  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sound familiar?&lt;/strong&gt; Let's fix this with Terraform.&lt;/p&gt;


&lt;h2&gt;
  
  
  🌐 What is a VPC? (Quick Theory)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Simple Definition
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;VPC (Virtual Private Cloud)&lt;/strong&gt; is your own private network in AWS. Think of it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Traditional Data Center:&lt;/strong&gt; Physical building with servers, switches, routers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPC:&lt;/strong&gt; Virtual data center with virtual servers, virtual switches, virtual routers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Point:&lt;/strong&gt; Your VPC is &lt;strong&gt;isolated&lt;/strong&gt; from other AWS accounts. It's YOUR private network.&lt;/p&gt;
&lt;h3&gt;
  
  
  VPC Components (The Building Blocks)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VPC (Your Private Network)
├── CIDR Block (IP Address Range)
├── Subnets (Subdivisions of your network)
│   ├── Public Subnets (Internet-accessible)
│   └── Private Subnets (Internal only)
├── Internet Gateway (Door to the internet)
├── NAT Gateway (Private subnet's internet access)
└── Route Tables (GPS for network traffic)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Understanding CIDR Blocks
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CIDR&lt;/strong&gt; = Classless Inter-Domain Routing (fancy name for IP address ranges)&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;10.0.0.0/16&lt;/code&gt; = 65,536 IP addresses (10.0.0.0 to 10.0.255.255)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;10.0.1.0/24&lt;/code&gt; = 256 IP addresses (10.0.1.0 to 10.0.1.255)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;10.0.2.0/24&lt;/code&gt; = 256 IP addresses (10.0.2.0 to 10.0.2.255)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Simple Rule:&lt;/strong&gt; Smaller number after &lt;code&gt;/&lt;/code&gt; = More IP addresses&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/16&lt;/code&gt; = 65,536 IPs (big network)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/24&lt;/code&gt; = 256 IPs (small network)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/32&lt;/code&gt; = 1 IP (single host)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't worry!&lt;/strong&gt; You don't need to be a networking expert. Just follow the patterns.&lt;/p&gt;
&lt;h3&gt;
  
  
  Public vs Private Subnets
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Public Subnet:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Has route to Internet Gateway&lt;/li&gt;
&lt;li&gt;✅ Resources get public IP addresses&lt;/li&gt;
&lt;li&gt;✅ Directly accessible from internet&lt;/li&gt;
&lt;li&gt;📍 Use for: Web servers, load balancers, bastion hosts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Private Subnet:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Has route to NAT Gateway (not Internet Gateway)&lt;/li&gt;
&lt;li&gt;❌ No public IP addresses&lt;/li&gt;
&lt;li&gt;❌ Not directly accessible from internet&lt;/li&gt;
&lt;li&gt;📍 Use for: Databases, application servers, internal services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why both?&lt;/strong&gt; Security! Keep sensitive resources (databases) in private subnets.&lt;/p&gt;


&lt;h2&gt;
  
  
  🏗️ What We'll Build Today
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Architecture Overview
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VPC: 10.0.0.0/16 (65,536 IPs)
│
├── Public Subnet 1: 10.0.1.0/24 (256 IPs) - us-east-1a
│   ├── Internet Gateway attached
│   └── Route: 0.0.0.0/0 → Internet Gateway
│
├── Private Subnet 1: 10.0.11.0/24 (256 IPs) - us-east-1a
│   └── Route: 0.0.0.0/0 → NAT Gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Why this design?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Single-AZ&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Public subnets&lt;/strong&gt; = For load balancers, web servers&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Private subnets&lt;/strong&gt; = For databases, application servers&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;NAT Gateway&lt;/strong&gt; = Private subnets can download updates&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Production-ready&lt;/strong&gt; = This is how real companies do it&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  📝 Step-by-Step: Building the VPC
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1: Create Project Directory
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/terraform-vpc-demo
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/terraform-vpc-demo
&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.amazonaws.com%2Fuploads%2Farticles%2Fgpa2nbdea2ajusf04zow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpa2nbdea2ajusf04zow.png" alt=" " width="729" height="72"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Create variables.tf
&lt;/h3&gt;

&lt;p&gt;Let's start with variables for flexibility:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano variables.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Copy this code:&lt;/strong&gt;&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="c1"&gt;# AWS Region&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"aws_region"&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;"AWS region where resources will be created"&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;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Project Name&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"project_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;"Project name to be used in resource naming"&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;"terraform-vpc"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Environment&lt;/span&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;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Environment name (dev, staging, prod)"&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# VPC CIDR Block&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"vpc_cidr"&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;"CIDR block for VPC"&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;"10.0.0.0/16"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Public Subnet CIDR&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"public_subnet_cidr"&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;"CIDR block for public subnet"&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;"10.0.1.0/24"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Private Subnet CIDR&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"private_subnet_cidr"&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;"CIDR block for private subnet"&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;"10.0.11.0/24"&lt;/span&gt;
&lt;span class="p"&gt;}&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.amazonaws.com%2Fuploads%2Farticles%2Fyod6syor5q2fe77r1t7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyod6syor5q2fe77r1t7r.png" alt=" " width="559" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's happening here?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All CIDR blocks are variables (easy to change)&lt;/li&gt;
&lt;li&gt;Project name and environment for tagging&lt;/li&gt;
&lt;li&gt;Default values provided (but can be overridden)&lt;/li&gt;
&lt;li&gt;Cost-optimized: 1 public + 1 private subnet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Save the file&lt;/strong&gt; (Ctrl+X, then Y, then Enter)&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Create terraform.tfvars
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Copy this code:&lt;/strong&gt;&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="c1"&gt;# Default configuration for development environment&lt;/span&gt;
&lt;span class="nx"&gt;aws_region&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="nx"&gt;project_name&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-vpc"&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;"dev"&lt;/span&gt;

&lt;span class="c1"&gt;# VPC Configuration&lt;/span&gt;
&lt;span class="nx"&gt;vpc_cidr&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;

&lt;span class="c1"&gt;# Subnets&lt;/span&gt;
&lt;span class="nx"&gt;public_subnet_cidr&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.1.0/24"&lt;/span&gt;
&lt;span class="nx"&gt;private_subnet_cidr&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.11.0/24"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Save the file&lt;/strong&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Step 4: Create main.tf (The Main Infrastructure)
&lt;/h3&gt;

&lt;p&gt;This is where the magic happens! We'll build it piece by piece.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano main.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Copy this code:&lt;/strong&gt;&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="c1"&gt;# Terraform configuration&lt;/span&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.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; 5.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="c1"&gt;# Provider configuration&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;span class="c1"&gt;# Data source: Get available availability zones&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_availability_zones"&lt;/span&gt; &lt;span class="s2"&gt;"available"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"available"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# VPC&lt;/span&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="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;enable_dns_hostnames&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;enable_dns_support&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;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-vpc"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Internet Gateway&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_internet_gateway"&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;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-igw"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Public Subnet 1&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"public_1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;cidr_block&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;public_subnet_1_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;availability_zone&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_availability_zones&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;map_public_ip_on_launch&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;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-public-subnet"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;Type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Public"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Private Subnet&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"private"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;cidr_block&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;private_subnet_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;availability_zone&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_availability_zones&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-private-subnet"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;Type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Private"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Elastic IP for NAT Gateway&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_eip"&lt;/span&gt; &lt;span class="s2"&gt;"nat"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;domain&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vpc"&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-nat-eip"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="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;span class="c1"&gt;# NAT Gateway&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_nat_gateway"&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;allocation_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_eip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nat&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_1&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;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-nat-gateway"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="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;span class="c1"&gt;# Public Route Table&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table"&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;route&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;"0.0.0.0/0"&lt;/span&gt;
    &lt;span class="nx"&gt;gateway_id&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="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-public-rt"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;Type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Public"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Private Route Table&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table"&lt;/span&gt; &lt;span class="s2"&gt;"private"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;route&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;"0.0.0.0/0"&lt;/span&gt;
    &lt;span class="nx"&gt;nat_gateway_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_nat_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="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"${var.project_name}-private-rt"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
    &lt;span class="nx"&gt;Type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Private"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Public Subnet Route Table Association&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table_association"&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt; &lt;span class="p"&gt;{&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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;route_table_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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="c1"&gt;# Private Subnet Route Table Association&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table_association"&lt;/span&gt; &lt;span class="s2"&gt;"private_1"&lt;/span&gt; &lt;span class="p"&gt;{&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private_1&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;route_table_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private&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="c1"&gt;# Private Subnet Route Table Association&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table_association"&lt;/span&gt; &lt;span class="s2"&gt;"private"&lt;/span&gt; &lt;span class="p"&gt;{&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private&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;route_table_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Save the file&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;That's the complete VPC infrastructure!&lt;/strong&gt; Let's break it down...&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Understanding the Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Data Source (NEW CONCEPT!)
&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;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_availability_zones"&lt;/span&gt; &lt;span class="s2"&gt;"available"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"available"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What's a data source?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resources&lt;/strong&gt; = Things Terraform &lt;strong&gt;creates&lt;/strong&gt; (VPC, subnets, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Sources&lt;/strong&gt; = Things Terraform &lt;strong&gt;reads&lt;/strong&gt; from AWS (AZs, AMIs, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why use it?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't hardcode availability zones (they differ by region)&lt;/li&gt;
&lt;li&gt;Automatically get available AZs&lt;/li&gt;
&lt;li&gt;Makes code portable across regions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How to use it:&lt;/strong&gt;&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;availability_zone&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_availability_zones&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# First AZ&lt;/span&gt;
&lt;span class="nx"&gt;availability_zone&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_availability_zones&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Second AZ&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. VPC Resource
&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;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="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;enable_dns_hostnames&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;# Important for EC2 instances&lt;/span&gt;
  &lt;span class="nx"&gt;enable_dns_support&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;# Important for DNS resolution&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;enable_dns_hostnames&lt;/code&gt; = EC2 instances get DNS names&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;enable_dns_support&lt;/code&gt; = DNS resolution works in VPC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Without these:&lt;/strong&gt; Your instances can't resolve domain names!&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Internet Gateway
&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;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_internet_gateway"&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;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;  &lt;span class="c1"&gt;# Attach to our VPC&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt; Allows public subnets to access the internet&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it as:&lt;/strong&gt; The front door of your VPC&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Public Subnets
&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;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"public_1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;cidr_block&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;public_subnet_1_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;availability_zone&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_availability_zones&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;map_public_ip_on_launch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;# Auto-assign public IPs&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key setting:&lt;/strong&gt; &lt;code&gt;map_public_ip_on_launch = true&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 instances in this subnet automatically get public IPs&lt;/li&gt;
&lt;li&gt;Makes them accessible from internet&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Private Subnets
&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;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"private_1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;cidr_block&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;private_subnet_1_cidr&lt;/span&gt;
  &lt;span class="nx"&gt;availability_zone&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_availability_zones&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="c1"&gt;# NO map_public_ip_on_launch = Private!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Notice:&lt;/strong&gt; No &lt;code&gt;map_public_ip_on_launch&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instances in private subnets don't get public IPs&lt;/li&gt;
&lt;li&gt;More secure for databases and internal services&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Elastic IP and NAT Gateway
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Elastic IP (static public IP)&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_eip"&lt;/span&gt; &lt;span class="s2"&gt;"nat"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;domain&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vpc"&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;span class="c1"&gt;# NAT Gateway (in public subnet!)&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_nat_gateway"&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;allocation_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_eip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nat&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;  &lt;span class="c1"&gt;# Must be in public subnet&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;&lt;strong&gt;What's NAT Gateway?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows private subnets to access internet (outbound only)&lt;/li&gt;
&lt;li&gt;Private instances can download updates, call APIs&lt;/li&gt;
&lt;li&gt;But internet can't initiate connections to private instances&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Elastic IP?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NAT Gateway needs a static public IP&lt;/li&gt;
&lt;li&gt;Elastic IP provides that&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚠️ COST WARNING:&lt;/strong&gt; NAT Gateway = $0.045/hour (~$32/month)&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Route Tables (The GPS)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Public Route Table:&lt;/strong&gt;&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_route_table"&lt;/span&gt; &lt;span class="s2"&gt;"public"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;route&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;"0.0.0.0/0"&lt;/span&gt;  &lt;span class="c1"&gt;# All traffic&lt;/span&gt;
    &lt;span class="nx"&gt;gateway_id&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="nx"&gt;id&lt;/span&gt;  &lt;span class="c1"&gt;# Goes to Internet Gateway&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Translation:&lt;/strong&gt; "Send all internet traffic (0.0.0.0/0) to the Internet Gateway"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Private Route Table:&lt;/strong&gt;&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_route_table"&lt;/span&gt; &lt;span class="s2"&gt;"private"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;route&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;"0.0.0.0/0"&lt;/span&gt;  &lt;span class="c1"&gt;# All traffic&lt;/span&gt;
    &lt;span class="nx"&gt;nat_gateway_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_nat_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="nx"&gt;id&lt;/span&gt;  &lt;span class="c1"&gt;# Goes to NAT Gateway&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Translation:&lt;/strong&gt; "Send all internet traffic (0.0.0.0/0) to the NAT Gateway"&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Route Table Associations
&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;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_route_table_association"&lt;/span&gt; &lt;span class="s2"&gt;"public_1"&lt;/span&gt; &lt;span class="p"&gt;{&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_1&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;route_table_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this does:&lt;/strong&gt; Links subnet to route table&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it as:&lt;/strong&gt; "Public Subnet 1, use the Public Route Table for routing"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without this:&lt;/strong&gt; Subnet doesn't know how to route traffic!&lt;/p&gt;




&lt;h2&gt;
  
  
  📤 Step 5: Create outputs.tf
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano outputs.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Copy this code:&lt;/strong&gt;&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="c1"&gt;# VPC Outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"vpc_id"&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;"ID of the VPC"&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;aws_vpc&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="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"vpc_cidr"&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;"CIDR block of the VPC"&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;aws_vpc&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="nx"&gt;cidr_block&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Subnet Outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"public_subnet_1_id"&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;"ID of public subnet 1"&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_1&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="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"public_subnet_2_id"&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;"ID of public subnet 2"&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_2&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="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"private_subnet_1_id"&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;"ID of private subnet 1"&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private_1&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="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"private_subnet_2_id"&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;"ID of private subnet 2"&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;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private_2&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="c1"&gt;# Gateway Outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"internet_gateway_id"&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;"ID of the Internet Gateway"&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;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="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"nat_gateway_id"&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;"ID of the NAT Gateway"&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;aws_nat_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="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"nat_gateway_public_ip"&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;"Public IP of the NAT Gateway"&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;aws_eip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nat&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;span class="c1"&gt;# Route Table Outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"public_route_table_id"&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;"ID of the public route table"&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;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public&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="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"private_route_table_id"&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;"ID of the private route table"&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;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private&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="c1"&gt;# Availability Zone&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"availability_zone"&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;"Availability zone used"&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_availability_zones&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Save the file&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Why so many outputs?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You'll need these IDs in Article 7 (EC2 + Load Balancer)&lt;/li&gt;
&lt;li&gt;Good documentation of what was created&lt;/li&gt;
&lt;li&gt;Easy to reference in other Terraform modules&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Let's Deploy the VPC!
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 6: Initialize Terraform
&lt;/h3&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;&lt;strong&gt;Expected output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Initializing the backend...
Initializing provider plugins...
&lt;/span&gt;&lt;span class="gp"&gt;- Finding hashicorp/aws versions matching "~&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;5.0&lt;span class="s2"&gt;"...
&lt;/span&gt;&lt;span class="go"&gt;- Installing hashicorp/aws v5.x.x...

Terraform has been successfully initialized!
&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.amazonaws.com%2Fuploads%2Farticles%2F58mvko1k1fdf1sniorad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58mvko1k1fdf1sniorad.png" alt=" " width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7: Plan the Infrastructure
&lt;/h3&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;&lt;strong&gt;What you'll see:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="nx"&gt;Terraform&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;perform&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;

  &lt;span class="c1"&gt;# aws_eip.nat will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_internet_gateway.main will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_nat_gateway.main will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_route_table.private will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_route_table.public will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_route_table_association.private_1 will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_route_table_association.private_2 will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_route_table_association.public_1 will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_route_table_association.public_2 will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_subnet.private_1 will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_subnet.private_2 will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_subnet.public_1 will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_subnet.public_2 will be created&lt;/span&gt;
  &lt;span class="c1"&gt;# aws_vpc.main will be created&lt;/span&gt;

&lt;span class="nx"&gt;Plan&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="err"&gt;.&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.amazonaws.com%2Fuploads%2Farticles%2Fcgly4u9pmll8zx75sfew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcgly4u9pmll8zx75sfew.png" alt=" " width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10 resources!&lt;/strong&gt; That's a complete VPC infrastructure from just one command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Review the plan carefully:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ VPC with correct CIDR (10.0.0.0/16)&lt;/li&gt;
&lt;li&gt;✅ 4 subnets with correct CIDRs&lt;/li&gt;
&lt;li&gt;✅ Subnets in different availability zones&lt;/li&gt;
&lt;li&gt;✅ Internet Gateway attached to VPC&lt;/li&gt;
&lt;li&gt;✅ NAT Gateway in public subnet&lt;/li&gt;
&lt;li&gt;✅ Route tables with correct routes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 8: Apply the Configuration
&lt;/h3&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;Type &lt;code&gt;yes&lt;/code&gt; when prompted.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Creating&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_vpc&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Creation&lt;/span&gt; &lt;span class="nx"&gt;complete&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;vpc-xxxxx&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="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Creating&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_subnet&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_1&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Creating&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_subnet&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Creating&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_subnet&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private_1&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Creating&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_subnet&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private_2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Creating&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_nat_gateway&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Creating&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_nat_gateway&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Still&lt;/span&gt; &lt;span class="nx"&gt;creating&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="nx"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;aws_nat_gateway&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Still&lt;/span&gt; &lt;span class="nx"&gt;creating&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="nx"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_nat_gateway&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Creation&lt;/span&gt; &lt;span class="nx"&gt;complete&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="mi"&gt;1m45&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;

&lt;span class="nx"&gt;Apply&lt;/span&gt; &lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="nx"&gt;Resources&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="nx"&gt;added&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;changed&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;destroyed&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;Outputs&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;

&lt;span class="nx"&gt;availability_zones&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;"us-east-1a"&lt;/span&gt;
&lt;span class="nx"&gt;internet_gateway_id&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"igw-xxxxx"&lt;/span&gt;
&lt;span class="nx"&gt;nat_gateway_id&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nat-xxxxx"&lt;/span&gt;
&lt;span class="nx"&gt;nat_gateway_public_ip&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"54.xxx.xxx.xxx"&lt;/span&gt;
&lt;span class="nx"&gt;private_route_table_id&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rtb-xxxxx"&lt;/span&gt;
&lt;span class="nx"&gt;private_subnet_id&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"subnet-xxxxx"&lt;/span&gt;
&lt;span class="nx"&gt;public_route_table_id&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rtb-xxxxx"&lt;/span&gt;
&lt;span class="nx"&gt;public_subnet_id&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"subnet-xxxxx"&lt;/span&gt;
&lt;span class="nx"&gt;vpc_cidr&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;
&lt;span class="nx"&gt;vpc_id&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vpc-xxxxx"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;⏱️ Time:&lt;/strong&gt; Takes about 2-3 minutes (NAT Gateway is slow to create)&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%2Fjnhcfsjsm9u2gdyy4lbi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnhcfsjsm9u2gdyy4lbi.png" alt=" " width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎉 Success!&lt;/strong&gt; You just created production-grade networking infrastructure!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 9: Verify in AWS Console
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Option 1: AWS CLI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get VPC ID&lt;/span&gt;
&lt;span class="nv"&gt;VPC_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;terraform output &lt;span class="nt"&gt;-raw&lt;/span&gt; vpc_id&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# List all subnets&lt;/span&gt;
aws ec2 describe-subnets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=vpc-id,Values=&lt;/span&gt;&lt;span class="nv"&gt;$VPC_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Subnets[*].[SubnetId,CidrBlock,AvailabilityZone,Tags[?Key==`Name`].Value|[0]]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&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.amazonaws.com%2Fuploads%2Farticles%2Faf4rgbz2xeg4htr2vae1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faf4rgbz2xeg4htr2vae1.png" alt=" " width="800" height="194"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check NAT Gateway&lt;/span&gt;
aws ec2 describe-nat-gateways &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="s2"&gt;"Name=vpc-id,Values=&lt;/span&gt;&lt;span class="nv"&gt;$VPC_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'NatGateways[*].[NatGatewayId,State,SubnetId]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&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.amazonaws.com%2Fuploads%2Farticles%2Fcgxz1d9exlbybvkxxj6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcgxz1d9exlbybvkxxj6o.png" alt=" " width="800" height="194"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check route tables&lt;/span&gt;
aws ec2 describe-route-tables &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=vpc-id,Values=&lt;/span&gt;&lt;span class="nv"&gt;$VPC_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'RouteTables[*].[RouteTableId,Tags[?Key==`Name`].Value|[0]]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&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.amazonaws.com%2Fuploads%2Farticles%2Fx2jqkdr6joz0hjo8o8nl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2jqkdr6joz0hjo8o8nl.png" alt=" " width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 2: AWS Console&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to AWS Console → VPC&lt;/li&gt;
&lt;li&gt;Find your VPC: &lt;code&gt;terraform-vpc-vpc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check:

&lt;ul&gt;
&lt;li&gt;✅ 2 subnets (1 public, 1 private)&lt;/li&gt;
&lt;li&gt;✅ Internet Gateway attached&lt;/li&gt;
&lt;li&gt;✅ NAT Gateway in public subnet&lt;/li&gt;
&lt;li&gt;✅ 2 route tables (public and private)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

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




&lt;h2&gt;
  
  
  🧠 Understanding Resource Dependencies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Implicit Dependencies
&lt;/h3&gt;

&lt;p&gt;Terraform automatically understands dependencies when you reference resources:&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_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"public_1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_vpc&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="nx"&gt;id&lt;/span&gt;  &lt;span class="c1"&gt;# References VPC&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Terraform knows:&lt;/strong&gt; "Create VPC first, then create subnet"&lt;/p&gt;

&lt;h3&gt;
  
  
  Explicit Dependencies
&lt;/h3&gt;

&lt;p&gt;Sometimes you need to force an order:&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_eip"&lt;/span&gt; &lt;span class="s2"&gt;"nat"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;domain&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vpc"&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="c1"&gt;# Explicit dependency&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; Elastic IP in VPC requires Internet Gateway to exist first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency Graph
&lt;/h3&gt;

&lt;p&gt;Terraform builds a graph of dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VPC
├── Internet Gateway
│   ├── Elastic IP
│   │   └── NAT Gateway
│   └── Public Route Table
│       └── Route Table Associations
└── Subnets
    └── Route Table Associations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Terraform creates resources in the correct order automatically!&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💰 Cost Breakdown
&lt;/h2&gt;

&lt;p&gt;Let's talk about costs (important!):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Cost&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;VPC&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;FREE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No charge for VPCs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Subnets&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;FREE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No charge for subnets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internet Gateway&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;FREE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No charge for IGW&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Elastic IP&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;FREE&lt;/strong&gt;*&lt;/td&gt;
&lt;td&gt;*When attached to running instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NAT Gateway&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.045/hour&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;~$32/month&lt;/strong&gt; ⚠️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Transfer&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.045/GB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Through NAT Gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Total for this setup: ~$32/month&lt;/strong&gt; (just for NAT Gateway)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚠️ IMPORTANT:&lt;/strong&gt; Always destroy test 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 destroy
&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.amazonaws.com%2Fuploads%2Farticles%2F45buf3zif9w6mk82bz1l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45buf3zif9w6mk82bz1l.png" alt=" " width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production Note:&lt;/strong&gt; In production, you'd have one NAT Gateway per AZ (2 NAT Gateways = $64/month) for high availability.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. CIDR Planning
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;✅ Plan CIDR blocks before creating VPC&lt;/li&gt;
&lt;li&gt;✅ Leave room for growth (use /16 for VPC)&lt;/li&gt;
&lt;li&gt;✅ Use non-overlapping ranges&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Use overlapping CIDR blocks&lt;/li&gt;
&lt;li&gt;❌ Make VPC too small (/24 = only 256 IPs)&lt;/li&gt;
&lt;li&gt;❌ Forget about VPC peering requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tool:&lt;/strong&gt; Use &lt;a href="https://www.ipaddressguide.com/cidr" rel="noopener noreferrer"&gt;CIDR Calculator&lt;/a&gt; for planning&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Multi-AZ Architecture
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Always use multiple availability zones:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ High availability&lt;/li&gt;
&lt;li&gt;✅ Fault tolerance&lt;/li&gt;
&lt;li&gt;✅ Better for production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Our setup:&lt;/strong&gt; 2 AZs (us-east-1a, us-east-1b)&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Tagging Strategy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Always tag resources:&lt;/strong&gt;&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;tags&lt;/span&gt; &lt;span class="err"&gt;=&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;"${var.project_name}-vpc"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;
  &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&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;"Learning"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Easy to identify resources&lt;/li&gt;
&lt;li&gt;Cost allocation&lt;/li&gt;
&lt;li&gt;Automation and filtering&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Separate Public and Private
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Security principle:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public subnets: Load balancers, bastion hosts&lt;/li&gt;
&lt;li&gt;Private subnets: Databases, application servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Never put databases in public subnets!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Use Variables
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Make everything configurable:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CIDR blocks&lt;/li&gt;
&lt;li&gt;Project name&lt;/li&gt;
&lt;li&gt;Environment&lt;/li&gt;
&lt;li&gt;Region&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Same code for dev, staging, prod&lt;/p&gt;




&lt;h2&gt;
  
  
  🐛 Common Issues &amp;amp; Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: NAT Gateway Creation Timeout
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&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;Error: timeout while waiting for state to become 'available'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;NAT Gateway takes 2-3 minutes to create&lt;/li&gt;
&lt;li&gt;This is normal, just wait&lt;/li&gt;
&lt;li&gt;If it fails, run &lt;code&gt;terraform apply&lt;/code&gt; again&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Issue 2: Elastic IP Limit Reached
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&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;Error: AddressLimitExceeded: The maximum number of addresses has been reached
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check current EIPs&lt;/span&gt;
aws ec2 describe-addresses

&lt;span class="c"&gt;# Release unused EIPs&lt;/span&gt;
aws ec2 release-address &lt;span class="nt"&gt;--allocation-id&lt;/span&gt; eipalloc-xxxxx

&lt;span class="c"&gt;# Or request limit increase in AWS Console&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue 3: Route Table Not Associated
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Subnet can't reach internet&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Check route table associations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-route-tables &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=vpc-id,Values=&lt;/span&gt;&lt;span class="nv"&gt;$VPC_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure each subnet has a route table association.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue 4: CIDR Block Overlap
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&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;Error: InvalidSubnet.Conflict: The CIDR 'x.x.x.x/x' conflicts with another subnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Check your CIDR blocks don't overlap&lt;/li&gt;
&lt;li&gt;Public: 10.0.1.0/24, 10.0.2.0/24&lt;/li&gt;
&lt;li&gt;Private: 10.0.11.0/24, 10.0.12.0/24&lt;/li&gt;
&lt;li&gt;No overlap!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Issue 5: Forgot to Destroy NAT Gateway
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Unexpected AWS bill&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check for NAT Gateways&lt;/span&gt;
aws ec2 describe-nat-gateways &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="s2"&gt;"Name=state,Values=available"&lt;/span&gt;

&lt;span class="c"&gt;# Destroy with Terraform&lt;/span&gt;
terraform destroy

&lt;span class="c"&gt;# Or manually delete in AWS Console&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧹 Cleanup (IMPORTANT!)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Don't forget this step!&lt;/strong&gt; NAT Gateway costs money.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Destroy all resources&lt;/span&gt;
terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type &lt;code&gt;yes&lt;/code&gt; when prompted.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="nx"&gt;aws_route_table_association&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private_2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Destroying&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_route_table_association&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;private_1&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Destroying&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_route_table_association&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Destroying&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_route_table_association&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_1&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Destroying&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_nat_gateway&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Destroying&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_nat_gateway&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Still&lt;/span&gt; &lt;span class="nx"&gt;destroying&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="nx"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;aws_nat_gateway&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Still&lt;/span&gt; &lt;span class="nx"&gt;destroying&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="nx"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;aws_nat_gateway&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Destruction&lt;/span&gt; &lt;span class="nx"&gt;complete&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="mi"&gt;1m30&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;
&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;Destroy&lt;/span&gt; &lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt; &lt;span class="nx"&gt;Resources&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="nx"&gt;destroyed&lt;/span&gt;&lt;span class="err"&gt;.&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.amazonaws.com%2Fuploads%2Farticles%2F9ipom70vgilwwsxiz48k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ipom70vgilwwsxiz48k.png" alt=" " width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verify deletion:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Should return empty&lt;/span&gt;
aws ec2 describe-vpcs &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=tag:Name,Values=terraform-vpc-vpc"&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.amazonaws.com%2Fuploads%2Farticles%2F6vzad28jaiizf5z5lbpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vzad28jaiizf5z5lbpc.png" alt=" " width="800" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clean up directory:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/terraform-vpc-demo
&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.amazonaws.com%2Fuploads%2Farticles%2Fqcca9h6pewb84r21gr5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcca9h6pewb84r21gr5u.png" alt=" " width="762" height="139"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 What You Learned
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;✅ VPC fundamentals (CIDR, subnets, routing)&lt;/li&gt;
&lt;li&gt;✅ Public vs Private subnets&lt;/li&gt;
&lt;li&gt;✅ Internet Gateway and NAT Gateway&lt;/li&gt;
&lt;li&gt;✅ Route tables and associations&lt;/li&gt;
&lt;li&gt;✅ Data sources (aws_availability_zones)&lt;/li&gt;
&lt;li&gt;✅ Resource dependencies (implicit and explicit)&lt;/li&gt;
&lt;li&gt;✅ Cost-optimized architecture&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;✅ Created production-ready VPC&lt;/li&gt;
&lt;li&gt;✅ Configured networking components&lt;/li&gt;
&lt;li&gt;✅ Used data sources&lt;/li&gt;
&lt;li&gt;✅ Managed complex infrastructure&lt;/li&gt;
&lt;li&gt;✅ Understood AWS networking costs&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;✅ 1 VPC&lt;/li&gt;
&lt;li&gt;✅ 2 Subnets (1 public, 1 private)&lt;/li&gt;
&lt;li&gt;✅ 1 Internet Gateway&lt;/li&gt;
&lt;li&gt;✅ 1 NAT Gateway&lt;/li&gt;
&lt;li&gt;✅ 2 Route Tables&lt;/li&gt;
&lt;li&gt;✅ Cost-optimized setup&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎓 Challenge: Extend Your VPC
&lt;/h2&gt;

&lt;p&gt;Try these modifications:&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Change CIDR blocks to 172.16.0.0/16&lt;/li&gt;
&lt;li&gt;Add a third availability zone&lt;/li&gt;
&lt;li&gt;Change project name and environment&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Add more private subnets (10.0.21.0/24, 10.0.22.0/24)&lt;/li&gt;
&lt;li&gt;Create separate route tables for each private subnet&lt;/li&gt;
&lt;li&gt;Add Network ACLs for additional security&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Add VPC Flow Logs&lt;/li&gt;
&lt;li&gt;Create a second NAT Gateway for high availability&lt;/li&gt;
&lt;li&gt;Add VPC endpoints for S3 and DynamoDB&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🔗 Useful Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/vpc/" rel="noopener noreferrer"&gt;AWS VPC Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc" rel="noopener noreferrer"&gt;Terraform AWS Provider - VPC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ipaddressguide.com/cidr" rel="noopener noreferrer"&gt;CIDR Calculator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/vpc/pricing/" rel="noopener noreferrer"&gt;AWS VPC Pricing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/simplynadaf/terraform-by-sarvar" rel="noopener noreferrer"&gt;GitHub Repo with Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 What's Next?
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;Article 7&lt;/strong&gt;, we'll deploy &lt;strong&gt;EC2 instances and an Application Load Balancer&lt;/strong&gt; in this VPC!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You'll learn:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch EC2 instances in public and private subnets&lt;/li&gt;
&lt;li&gt;Configure security groups&lt;/li&gt;
&lt;li&gt;Create an Application Load Balancer&lt;/li&gt;
&lt;li&gt;Set up health checks&lt;/li&gt;
&lt;li&gt;Test the complete architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time:&lt;/strong&gt; 45 minutes&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Difficulty:&lt;/strong&gt; Intermediate&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Full web application infrastructure&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading. I hope this article provided practical insights and a clearer understanding of the topic.&lt;/p&gt;

&lt;p&gt;If you found this useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value
&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today
&lt;/li&gt;
&lt;li&gt;💾 Save it for your next optimization session
&lt;/li&gt;
&lt;li&gt;🔄 Share it with your team
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives are coming soon on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Operations&lt;/li&gt;
&lt;li&gt;GenAI &amp;amp; Agentic AI&lt;/li&gt;
&lt;li&gt;DevOps Automation&lt;/li&gt;
&lt;li&gt;Data &amp;amp; Platform Engineering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow along for weekly insights and hands-on guides.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts. Feel free to drop a comment or connect with me on:&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, reach out at:&lt;/p&gt;

&lt;p&gt;📧 &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Found this helpful? Share it with your team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⭐ Star the repo • 📖 Follow the series • 💬 Ask questions  &lt;/p&gt;

&lt;p&gt;Made by &lt;strong&gt;Sarvar Nadaf&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🌐 &lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;https://sarvarnadaf.com&lt;/a&gt;&lt;/p&gt;




</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Connecting 12 MCP Servers to Amazon Q CLI: What Broke and How I Fixed It</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Mon, 06 Apr 2026 13:02:02 +0000</pubDate>
      <link>https://forem.com/aws-builders/connecting-12-mcp-servers-to-amazon-q-cli-what-broke-and-how-i-fixed-it-48mj</link>
      <guid>https://forem.com/aws-builders/connecting-12-mcp-servers-to-amazon-q-cli-what-broke-and-how-i-fixed-it-48mj</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;

&lt;p&gt;Let's dive in and explore the fascinating world of cloud technology together! 🚀&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Written from experience building AI agent integrations for AWS infrastructure management. Your mileage may vary, but the principles hold across different use cases.&lt;/em&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Do We Still Need MCP When We Have Agent Skills?
&lt;/h1&gt;

&lt;p&gt;As a cloud architect working with AI agents, I've spent the last few months exploring how to extend their capabilities. Specifically, I've been working with Amazon Q Developer Pro - AWS's AI assistant that helps with coding, infrastructure management, and cloud operations through a chat interface.&lt;/p&gt;

&lt;p&gt;This article shares what I learned about two different approaches to extending AI agents: Model Context Protocol (MCP) and Agent Skills. While the specific implementation details are still evolving, the architectural patterns I describe here represent where the ecosystem is heading based on current capabilities and community standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem I Was Solving
&lt;/h2&gt;

&lt;p&gt;I needed Amazon Q Developer Pro to help me manage AWS infrastructure across multiple accounts. The agent needed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check CloudWatch metrics&lt;/li&gt;
&lt;li&gt;Query RDS databases&lt;/li&gt;
&lt;li&gt;Send alerts to Slack&lt;/li&gt;
&lt;li&gt;Generate cost reports&lt;/li&gt;
&lt;li&gt;Review CloudFormation templates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I tried two approaches, and each had serious problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 1: Connecting Everything via MCP
&lt;/h2&gt;

&lt;p&gt;MCP is a standard protocol that lets AI agents connect to external tools. Think of it like USB ports on your computer - one standard interface that works with many devices.&lt;/p&gt;

&lt;p&gt;I connected 12 MCP servers to Amazon Q Developer Pro:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS CloudWatch server&lt;/li&gt;
&lt;li&gt;RDS query server&lt;/li&gt;
&lt;li&gt;Slack messaging server&lt;/li&gt;
&lt;li&gt;Cost Explorer server&lt;/li&gt;
&lt;li&gt;GitHub server&lt;/li&gt;
&lt;li&gt;And seven more&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What Went Wrong
&lt;/h3&gt;

&lt;p&gt;Before I even asked a question, 35% of the context window was already full. Each MCP server loaded all its available functions into memory. The CloudWatch server alone exposed 15 different functions with detailed parameter descriptions.&lt;/p&gt;

&lt;p&gt;When I asked Amazon Q Developer Pro to "check if our xyz database is healthy," it had to scan through multiple function definitions to figure out which ones to use. Sometimes it picked the wrong ones.&lt;/p&gt;

&lt;p&gt;Every function call and response consumed more context. After three or four operations, I was running out of space for the actual conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 2: Using Agent Skills
&lt;/h2&gt;

&lt;p&gt;Agent Skills are different. Instead of connecting to external tools, you give the agent domain knowledge - a guide on how to think about a problem.&lt;/p&gt;

&lt;p&gt;I created a skill called "database-health-check" with a simple file structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;database-health-check/
  SKILL.md          (when to use this, what steps to follow)
  scripts/
    check_rds.py    (Python script to query RDS)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SKILL.md file contained:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Database Health Check Skill&lt;/span&gt;

&lt;span class="gu"&gt;## Trigger&lt;/span&gt;
Keywords: "database health", "RDS status", "database performance", "DB issues"

&lt;span class="gu"&gt;## Process&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; Check CPU utilization (threshold: 80%)
&lt;span class="p"&gt;2.&lt;/span&gt; Check active connections (threshold: 90% of max)
&lt;span class="p"&gt;3.&lt;/span&gt; Check replication lag (threshold: 1000ms)
&lt;span class="p"&gt;4.&lt;/span&gt; Check storage space (threshold: 85%)

&lt;span class="gu"&gt;## Decision Logic&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; If CPU &amp;gt; 80%: WARN - "High CPU usage detected"
&lt;span class="p"&gt;-&lt;/span&gt; If connections &amp;gt; 90%: CRITICAL - "Connection pool nearly exhausted"
&lt;span class="p"&gt;-&lt;/span&gt; If replication lag &amp;gt; 1000ms: WARN - "Replication falling behind"
&lt;span class="p"&gt;-&lt;/span&gt; If storage &amp;gt; 85%: CRITICAL - "Low storage space"

&lt;span class="gu"&gt;## Output Format&lt;/span&gt;
Status: [HEALTHY|WARN|CRITICAL]
Issues: [list of problems found]
Recommendations: [suggested actions]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Went Wrong
&lt;/h3&gt;

&lt;p&gt;The skill worked perfectly on my laptop. Then my colleague tried to use it and got an error: "ModuleNotFoundError: No module named 'boto3'".&lt;/p&gt;

&lt;p&gt;The Python script needed boto3, pandas, and psycopg2. My machine had them installed. His didn't. We had no standard way to declare or install these dependencies.&lt;/p&gt;

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

&lt;p&gt;After working with both, I realized they solve different problems:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP answers: "What can I do?"&lt;/strong&gt;&lt;br&gt;
It provides capabilities - functions the agent can call. Each MCP server is self-contained with its own dependencies and environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skills answer: "How should I think?"&lt;/strong&gt;&lt;br&gt;
They provide expertise - decision logic, quality standards, and workflows. But they run in whatever environment the agent has.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution: Use Both Together
&lt;/h2&gt;

&lt;p&gt;Here's what actually works in real time. I'll use a real example from last week.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example: Automated Cost Anomaly Detection
&lt;/h3&gt;

&lt;p&gt;I needed Amazon Q Developer Pro to monitor our AWS costs and alert us when something unusual happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The MCP Layer (The Hands)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I set up two MCP servers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;aws-cost-explorer-mcp - exposes functions like get_daily_costs(), get_service_breakdown()&lt;/li&gt;
&lt;li&gt;slack-notifications-mcp - exposes send_message(), create_incident()&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each server runs in its own Docker container with all dependencies installed. Amazon Q Developer Pro doesn't need to know about boto3 or the Slack SDK.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Skill Layer (The Brain)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I created a cost-monitoring skill with this logic in SKILL.md:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Trigger: When user asks about cost anomalies or unusual spending

Process:
&lt;span class="p"&gt;1.&lt;/span&gt; Get last 30 days of daily costs
&lt;span class="p"&gt;2.&lt;/span&gt; Calculate average and standard deviation
&lt;span class="p"&gt;3.&lt;/span&gt; Check if today's cost is more than 2 standard deviations above average
&lt;span class="p"&gt;4.&lt;/span&gt; If yes, get service breakdown to identify which service spiked
&lt;span class="p"&gt;5.&lt;/span&gt; If spike is over $500, send high-priority Slack alert
&lt;span class="p"&gt;6.&lt;/span&gt; If spike is under $500, just report in conversation

Quality checks:
&lt;span class="p"&gt;-&lt;/span&gt; Always compare against same day of week (Monday vs Monday)
&lt;span class="p"&gt;-&lt;/span&gt; Exclude known scheduled events (monthly backups, etc.)
&lt;span class="p"&gt;-&lt;/span&gt; Include percentage change, not just absolute numbers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How They Work Together&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I ask Amazon Q Developer Pro: "Are our AWS costs normal today?"&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Amazon Q Developer Pro matches the question to the cost-monitoring skill&lt;/li&gt;
&lt;li&gt;The skill loads its SKILL.md (only 2KB of context)&lt;/li&gt;
&lt;li&gt;The skill requires cost data, so Amazon Q Developer Pro connects to the aws-cost-explorer-mcp server&lt;/li&gt;
&lt;li&gt;The skill orchestrates: call get_daily_costs(), analyze the data, decide if it's anomalous&lt;/li&gt;
&lt;li&gt;If anomalous, the skill calls the slack-notifications-mcp server&lt;/li&gt;
&lt;li&gt;After completion, the skill unloads from memory&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The MCP servers handle the technical execution. The skill handles the business logic and decision-making.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Architecture Works
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Context Efficiency&lt;/strong&gt;&lt;br&gt;
Only the active skill loads into memory. MCP tools load on-demand when the skill needs them. I went from 35% context consumed at startup to 5%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Portability&lt;/strong&gt;&lt;br&gt;
The same skill works on my laptop, my colleague's Windows machine, and our CI/CD pipeline. The MCP servers can run locally, in containers, or as remote services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reusability&lt;/strong&gt;&lt;br&gt;
The aws-cost-explorer-mcp server is used by three different skills:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cost-monitoring (detects anomalies)&lt;/li&gt;
&lt;li&gt;budget-planning (forecasts spending)&lt;/li&gt;
&lt;li&gt;cost-optimization (finds savings opportunities)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each skill brings different expertise, but they share the same data source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;&lt;br&gt;
When AWS changes their Cost Explorer API, I update one MCP server. All skills continue working. When business rules change (new alert thresholds), I update the skill. The MCP servers don't need to change.&lt;/p&gt;
&lt;h2&gt;
  
  
  Visual Overview
&lt;/h2&gt;

&lt;p&gt;Here's how the three layers work together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────┐
│   Agent Layer (Amazon Q Developer Pro)  │
│   Matches tasks → Loads skills          │
│   Connects to MCP servers               │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│         Skill Layer (The Brain)         │
│   cost-monitoring.SKILL.md              │
│   - When to trigger                     │
│   - Decision logic                      │
│   - Quality checks                      │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│         MCP Layer (The Hands)           │
│   aws-cost-explorer-mcp                 │
│   slack-notifications-mcp               │
│   - Tool execution                      │
│   - Environment isolation               │
└─────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Practical Pattern
&lt;/h2&gt;

&lt;p&gt;Here's the decision framework I use:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Put it in an MCP server if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple skills will use it&lt;/li&gt;
&lt;li&gt;It has heavy dependencies (Python libraries, system tools)&lt;/li&gt;
&lt;li&gt;It needs credentials or secrets&lt;/li&gt;
&lt;li&gt;It's a stable, reusable capability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Put it in a skill if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's domain knowledge or business logic&lt;/li&gt;
&lt;li&gt;It orchestrates multiple tools&lt;/li&gt;
&lt;li&gt;It has conditional decision-making&lt;/li&gt;
&lt;li&gt;It's specific to one workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep it as a simple script if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's a one-time operation&lt;/li&gt;
&lt;li&gt;The entire workflow is tightly coupled&lt;/li&gt;
&lt;li&gt;Splitting it would add unnecessary complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Still Missing
&lt;/h2&gt;

&lt;p&gt;The ecosystem isn't mature yet. Here's what I wish existed:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency Declaration&lt;/strong&gt;&lt;br&gt;
Skills need a standard way to say "I need these capabilities" without hardcoding specific MCP servers. Something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;requires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cloud_metrics&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;notifications&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the runtime figures out which MCP servers provide those capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dynamic Loading&lt;/strong&gt;&lt;br&gt;
Right now, when you connect an MCP server, all its tools load immediately. I want skills to control this: "Load only the cost analysis tools for this task."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Graceful Fallback&lt;/strong&gt;&lt;br&gt;
If an MCP server is unavailable, the skill should automatically fall back to a built-in script or tell me clearly what's missing.&lt;/p&gt;

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

&lt;p&gt;After six months of exploring these patterns with Amazon Q Developer Pro and other AI agents, here's what I know:&lt;/p&gt;

&lt;p&gt;MCP and Agent Skills aren't competing approaches. They're complementary layers of the same system.&lt;/p&gt;

&lt;p&gt;MCP gives your agent reliable, isolated capabilities. Skills give your agent the expertise to use those capabilities intelligently.&lt;/p&gt;

&lt;p&gt;You need both. MCP without skills is a toolbox with no craftsman. Skills without MCP are expertise with unreliable tools.&lt;/p&gt;

&lt;p&gt;The architecture that works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skills encode what to do and when&lt;/li&gt;
&lt;li&gt;MCP servers provide how to do it&lt;/li&gt;
&lt;li&gt;The agent runtime connects them together&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't just theoretical. These patterns are being implemented in actual environments, managing real AWS infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;If you want to explore this architecture:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For MCP:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the official MCP specification at modelcontextprotocol.io&lt;/li&gt;
&lt;li&gt;Browse existing MCP servers at github.com/modelcontextprotocol/servers&lt;/li&gt;
&lt;li&gt;Amazon Q Developer supports MCP through the Q CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For Agent Skills:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Review the Agent Skills specification by Anthropic&lt;/li&gt;
&lt;li&gt;Start with simple skills that encode your team's operational knowledge&lt;/li&gt;
&lt;li&gt;Focus on decision logic and workflows, not heavy computation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Next Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify one repetitive task you do with your AI agent&lt;/li&gt;
&lt;li&gt;Ask: Does this need external tools (MCP) or decision logic (Skill)?&lt;/li&gt;
&lt;li&gt;Build the simplest version that works&lt;/li&gt;
&lt;li&gt;Iterate based on what you learn&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The ecosystem is still maturing, but the core patterns are solid. Start small, learn from erros, and build up from there.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading! I hope this article gave you practical insights and a clearer perspective on the topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Was this helpful?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today&lt;/li&gt;
&lt;li&gt;💾 Save for your next optimization session&lt;/li&gt;
&lt;li&gt;🔄 Share with your team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Follow me for more on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS architecture patterns&lt;/li&gt;
&lt;li&gt;FinOps automation&lt;/li&gt;
&lt;li&gt;Multi-account strategies&lt;/li&gt;
&lt;li&gt;AI-driven DevOps&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives coming soon on cloud operations, GenAI, Agentic-AI, DevOps, and data workflows follow for weekly insights.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts drop a comment or connect with me on &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, feel free to reach out directly at &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Learning&lt;/strong&gt; 🚀&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>discuss</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Terraform Variables and Outputs: Making Your Infrastructure Flexible</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Wed, 01 Apr 2026 09:59:13 +0000</pubDate>
      <link>https://forem.com/aws-builders/terraform-variables-and-outputs-making-your-infrastructure-flexible-3ebc</link>
      <guid>https://forem.com/aws-builders/terraform-variables-and-outputs-making-your-infrastructure-flexible-3ebc</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The difference between a script and reusable infrastructure code is variables."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🎯 Welcome Back!
&lt;/h2&gt;

&lt;p&gt;Remember in &lt;a href="https://dev.to/aws-builders/your-first-infrastructure-as-code-in-four-commands-46ep"&gt;Article 3&lt;/a&gt; when you created that S3 bucket? You hardcoded the bucket name directly in the code:&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_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"my_first_bucket"&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;"terraform-first-bucket-yourname-2026"&lt;/span&gt;  &lt;span class="c1"&gt;# Hardcoded!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;That works... once.&lt;/strong&gt; But what if you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10 buckets with different names?&lt;/li&gt;
&lt;li&gt;Same code for dev, staging, and production?&lt;/li&gt;
&lt;li&gt;To let your team customize configurations?&lt;/li&gt;
&lt;li&gt;To reuse this code in different projects?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Today, you'll learn how to make your Terraform code flexible and reusable&lt;/strong&gt; using variables and outputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the end of this article, you'll:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Convert hardcoded values to variables&lt;/li&gt;
&lt;li&gt;✅ Use all variable types (string, number, bool, list, map)&lt;/li&gt;
&lt;li&gt;✅ Work with &lt;code&gt;terraform.tfvars&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;✅ Create outputs to expose information&lt;/li&gt;
&lt;li&gt;✅ Build dev/prod configurations from the same code&lt;/li&gt;
&lt;li&gt;✅ Use variable validation and sensitive values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time Required:&lt;/strong&gt; 30 minutes&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; $0 (using free tier resources)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Difficulty:&lt;/strong&gt; Beginner-friendly&lt;/p&gt;

&lt;p&gt;Let's make your code reusable! 🚀&lt;/p&gt;


&lt;h2&gt;
  
  
  💔 The Problem: Hardcoded Hell
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Painful Reality
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1: Multiple Environments&lt;/strong&gt;&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="c1"&gt;# dev.tf&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"app"&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;"myapp-dev-bucket"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# staging.tf (copy-paste and change)&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"app"&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;"myapp-staging-bucket"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# prod.tf (copy-paste and change again)&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"app"&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;"myapp-prod-bucket"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;❌ Three copies of the same code&lt;/li&gt;
&lt;li&gt;❌ Change one thing = update three files&lt;/li&gt;
&lt;li&gt;❌ High risk of mistakes&lt;/li&gt;
&lt;li&gt;❌ Nightmare to maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Scenario 2: Team Collaboration&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;Developer 1: "I need the bucket name to be X"
Developer 2: "I need it to be Y"
DevOps: "Production needs Z"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everyone edits the same &lt;code&gt;.tf&lt;/code&gt; file = merge conflicts and chaos!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There's a better way.&lt;/strong&gt; Enter variables.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 What Are Variables?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Simple Definition
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Variables are like function parameters for your infrastructure code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of it like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without Variables (Hardcoded):&lt;/strong&gt;&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createBucket&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-hardcoded-bucket-name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With Variables (Flexible):&lt;/strong&gt;&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucketName&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;bucketName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;createBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev-bucket&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    &lt;span class="c1"&gt;// Different uses&lt;/span&gt;
&lt;span class="nf"&gt;createBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prod-bucket&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// Same code!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In Terraform:&lt;/strong&gt;&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="c1"&gt;# Define the variable&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"bucket_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 the S3 bucket"&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;span class="c1"&gt;# Use the variable&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"app"&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="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket_name&lt;/span&gt;  &lt;span class="c1"&gt;# Reference with var.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Same code, different values!&lt;/strong&gt; That's the power of variables.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Hands-On: Your First Variable
&lt;/h2&gt;

&lt;p&gt;Let's convert our hardcoded S3 bucket to use variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create Project Directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/terraform-variables-demo
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/terraform-variables-demo
&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.amazonaws.com%2Fuploads%2Farticles%2Fr175ghbc7sfdr4p7tjbi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr175ghbc7sfdr4p7tjbi.png" alt=" " width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create variables.tf
&lt;/h3&gt;

&lt;p&gt;Create a new file called &lt;code&gt;variables.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano variables.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add this code:&lt;/strong&gt;&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="c1"&gt;# String variable - for text values&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"aws_region"&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;"AWS region where resources will be created"&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;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"bucket_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 the S3 bucket (must be globally unique)"&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="c1"&gt;# No default - user must provide this value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Map variable - for key-value pairs like tags&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"common_tags"&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;"Common tags to apply to all resources"&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="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&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="s2"&gt;"Development"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&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;"Learning"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;strong&gt;Understanding the syntax:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt; - Explains what the variable is for (always add this!)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt; - What kind of value (string, number, bool, list, map)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;default&lt;/code&gt; - Optional default value (if not provided, user must supply it)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Create main.tf
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano main.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add this code:&lt;/strong&gt;&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.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; 5.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="c1"&gt;# Use variable in provider&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="c1"&gt;# Reference variable with var.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Use variables in resource&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&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;bucket&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;bucket_name&lt;/span&gt;  &lt;span class="c1"&gt;# Variable for bucket name&lt;/span&gt;

  &lt;span class="c1"&gt;# Merge common_tags with specific tags&lt;/span&gt;
  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merge&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;common_tags&lt;/span&gt;&lt;span class="p"&gt;,&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;bucket_name&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;strong&gt;Notice:&lt;/strong&gt; We reference variables with &lt;code&gt;var.variable_name&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Initialize and Test
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Terraform will prompt you:&lt;/strong&gt;&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;bucket_name&lt;/span&gt;
  &lt;span class="nx"&gt;Name&lt;/span&gt; &lt;span class="nx"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;S3&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;must&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;globally&lt;/span&gt; &lt;span class="nx"&gt;unique&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;Enter&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="err"&gt;:&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.amazonaws.com%2Fuploads%2Farticles%2F0uvoffgtufuxvj3iloio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0uvoffgtufuxvj3iloio.png" alt=" " width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; &lt;code&gt;my-first-variable-bucket-yourname-2026&lt;/code&gt; and press Enter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You'll see the plan:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="nx"&gt;Terraform&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;perform&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;

  &lt;span class="c1"&gt;# aws_s3_bucket.example will be created&lt;/span&gt;
  &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="err"&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-first-variable-bucket-yourname-2026"&lt;/span&gt;
      &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Development"&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"ManagedBy"&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-first-variable-bucket-yourname-2026"&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"Project"&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Learning"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Plan&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="err"&gt;.&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.amazonaws.com%2Fuploads%2Farticles%2Fjbfk838xhhbwetmx7pdm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbfk838xhhbwetmx7pdm.png" alt=" " width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't apply yet!&lt;/strong&gt; Let's learn better ways to pass variables.&lt;/p&gt;




&lt;h2&gt;
  
  
  📝 Three Ways to Pass Variables
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Method 1: Command Line (What We Just Did)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform plan
&lt;span class="c"&gt;# Terraform prompts for bucket_name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Interactive&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Tedious for multiple variables&lt;/p&gt;
&lt;h3&gt;
  
  
  Method 2: Command Line Flags
&lt;/h3&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;-var&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bucket_name=my-bucket-2026"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Good for CI/CD pipelines&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Long commands with many variables&lt;/p&gt;
&lt;h3&gt;
  
  
  Method 3: terraform.tfvars File (Best for Most Cases)
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;terraform.tfvars&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add this:&lt;/strong&gt;&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;bucket_name&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-variable-bucket-yourname-2026"&lt;/span&gt;
&lt;span class="nx"&gt;aws_region&lt;/span&gt;  &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;

&lt;span class="nx"&gt;common_tags&lt;/span&gt; &lt;span class="err"&gt;=&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="s2"&gt;"Development"&lt;/span&gt;
  &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&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;"Variables Demo"&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;"YourName"&lt;/span&gt;
&lt;span class="p"&gt;}&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.amazonaws.com%2Fuploads%2Farticles%2Fqeablxn4uhnkuotlgrvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqeablxn4uhnkuotlgrvg.png" alt=" " width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now run:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;No prompts!&lt;/strong&gt; Terraform automatically loads &lt;code&gt;terraform.tfvars&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apply it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Type &lt;code&gt;yes&lt;/code&gt; when prompted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎉 Success!&lt;/strong&gt; You just created infrastructure using variables!&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%2F49332euimjyuq1la6j58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49332euimjyuq1la6j58.png" alt=" " width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎨 Variable Types: The Complete Guide
&lt;/h2&gt;

&lt;p&gt;Terraform supports multiple variable types. Let's explore them all!&lt;/p&gt;

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

&lt;p&gt;Replace your &lt;code&gt;variables.tf&lt;/code&gt; with this comprehensive version:&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="c1"&gt;# 1. STRING - Text values&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"aws_region"&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;"AWS region where resources will be created"&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;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"bucket_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 the S3 bucket (must be globally unique)"&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;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"bucket_prefix"&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;"Prefix for multiple bucket names"&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;"terraform-demo"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# 2. NUMBER - Numeric values&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"bucket_count"&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;"Number of S3 buckets to create"&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="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

  &lt;span class="c1"&gt;# Validation rule&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket_count&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="err"&gt;&amp;amp;&amp;amp;&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;bucket_count&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&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 count must be between 1 and 5."&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. BOOLEAN - True/False values&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"enable_versioning"&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;"Enable versioning on the S3 bucket"&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="nx"&gt;default&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;span class="c1"&gt;# 4. LIST - Ordered collection of values&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"allowed_ips"&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;"List of IP addresses allowed to access the bucket"&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;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;default&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;# 5. MAP - Key-value pairs&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"common_tags"&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;"Common tags to apply to all resources"&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="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&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="s2"&gt;"Development"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&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;"Learning"&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. ENVIRONMENT - With validation&lt;/span&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;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Environment name (dev, staging, prod)"&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="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;h3&gt;
  
  
  Update main.tf to Use All Variable Types
&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;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.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; 5.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;span class="c1"&gt;# Main S3 bucket with variables&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&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;bucket&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;bucket_name&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merge&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;common_tags&lt;/span&gt;&lt;span class="p"&gt;,&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;bucket_name&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;# Conditional resource - only created if enable_versioning is true&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket_versioning"&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;count&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;enable_versioning&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# Conditional creation&lt;/span&gt;
  &lt;span class="nx"&gt;bucket&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;example&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;versioning_configuration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Enabled"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Multiple buckets using count (number variable)&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"multiple"&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="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket_count&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;"${var.bucket_prefix}-${count.index + 1}-yourname-2026"&lt;/span&gt;

  &lt;span class="nx"&gt;tags&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;common_tags&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What's happening here:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;var.enable_versioning ? 1 : 0&lt;/code&gt; - Conditional: if true, create 1 resource; if false, create 0&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;count = var.bucket_count&lt;/code&gt; - Create multiple resources based on number&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;count.index&lt;/code&gt; - Access the current index (0, 1, 2...)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;merge()&lt;/code&gt; - Combine two maps together&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📤 Outputs: Exposing Information
&lt;/h2&gt;

&lt;p&gt;Variables let data IN. Outputs let data OUT.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Outputs Matter
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Display important information after &lt;code&gt;terraform apply&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Pass values to other Terraform modules&lt;/li&gt;
&lt;li&gt;Use in scripts or CI/CD pipelines&lt;/li&gt;
&lt;li&gt;Share information with team members&lt;/li&gt;
&lt;/ul&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano outputs.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add this code:&lt;/strong&gt;&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="c1"&gt;# Basic outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_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 the created S3 bucket"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&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="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_arn"&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;"ARN of the S3 bucket"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_region"&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;"Region where the bucket was created"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&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;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_domain_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;"Domain name of the bucket"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket_domain_name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Multiple buckets output&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"multiple_bucket_names"&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;"Names of all created buckets"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;multiple&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="c1"&gt;# Conditional output&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"versioning_enabled"&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;"Whether versioning is enabled"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enable_versioning&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Map output&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_tags"&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;"Tags applied to the bucket"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Sensitive output example&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_id_sensitive"&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;"Bucket ID (marked as sensitive)"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&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;sensitive&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;# Won't display in plan/apply output&lt;/span&gt;
&lt;span class="p"&gt;}&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.amazonaws.com%2Fuploads%2Farticles%2F075lobp3ssdxq9s36ryr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F075lobp3ssdxq9s36ryr.png" alt=" " width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Update terraform.tfvars
&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;bucket_name&lt;/span&gt;      &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-variable-bucket-yourname-2026"&lt;/span&gt;
&lt;span class="nx"&gt;bucket_prefix&lt;/span&gt;    &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"demo-bucket-yourname"&lt;/span&gt;
&lt;span class="nx"&gt;bucket_count&lt;/span&gt;     &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="nx"&gt;enable_versioning&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="nx"&gt;aws_region&lt;/span&gt;       &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;

&lt;span class="nx"&gt;common_tags&lt;/span&gt; &lt;span class="err"&gt;=&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="s2"&gt;"Development"&lt;/span&gt;
  &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&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;"Variables Demo"&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;"YourName"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Apply and See Outputs
&lt;/h3&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;&lt;strong&gt;After applying, you'll see:&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;Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

bucket_arn = "arn:aws:s3:::my-variable-bucket-yourname-2026"
bucket_domain_name = "my-variable-bucket-yourname-2026.s3.amazonaws.com"
bucket_id_sensitive = &amp;lt;sensitive&amp;gt;
bucket_name = "my-variable-bucket-yourname-2026"
bucket_region = "us-east-1"
bucket_tags = tomap({
  "Environment" = "Development"
  "ManagedBy" = "Terraform"
  "Name" = "my-variable-bucket-yourname-2026"
  "Owner" = "YourName"
  "Project" = "Variables Demo"
})
multiple_bucket_names = [
  "demo-bucket-yourname-1-yourname-2026",
  "demo-bucket-yourname-2-yourname-2026",
]
versioning_enabled = true
&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.amazonaws.com%2Fuploads%2Farticles%2Fx9ruu0jp0nf7dwhc00qd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9ruu0jp0nf7dwhc00qd.png" alt=" " width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  View Outputs Anytime
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# View all outputs&lt;/span&gt;
terraform output

&lt;span class="c"&gt;# View specific output&lt;/span&gt;
terraform output bucket_name

&lt;span class="c"&gt;# View sensitive output (will reveal the value)&lt;/span&gt;
terraform output bucket_id_sensitive

&lt;span class="c"&gt;# Output as JSON (useful for scripts)&lt;/span&gt;
terraform output &lt;span class="nt"&gt;-json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🌍 Real-World: Dev vs Prod Configurations
&lt;/h2&gt;

&lt;p&gt;The real power of variables: &lt;strong&gt;same code, different configurations!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create dev.tfvars
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano dev.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Development environment configuration&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;"dev"&lt;/span&gt;
&lt;span class="nx"&gt;bucket_name&lt;/span&gt;       &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myapp-dev-yourname-2026"&lt;/span&gt;
&lt;span class="nx"&gt;bucket_prefix&lt;/span&gt;     &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myapp-dev-yourname"&lt;/span&gt;
&lt;span class="nx"&gt;bucket_count&lt;/span&gt;      &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="nx"&gt;enable_versioning&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;  &lt;span class="c1"&gt;# Save costs in dev&lt;/span&gt;
&lt;span class="nx"&gt;aws_region&lt;/span&gt;        &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;

&lt;span class="nx"&gt;common_tags&lt;/span&gt; &lt;span class="err"&gt;=&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="s2"&gt;"Development"&lt;/span&gt;
  &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&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;"MyApp"&lt;/span&gt;
  &lt;span class="nx"&gt;CostCenter&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Engineering"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create prod.tfvars
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano prod.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Production environment configuration&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="nx"&gt;bucket_name&lt;/span&gt;       &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myapp-prod-yourname-2026"&lt;/span&gt;
&lt;span class="nx"&gt;bucket_prefix&lt;/span&gt;     &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myapp-prod-yourname"&lt;/span&gt;
&lt;span class="nx"&gt;bucket_count&lt;/span&gt;      &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="nx"&gt;enable_versioning&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;# Important for prod!&lt;/span&gt;
&lt;span class="nx"&gt;aws_region&lt;/span&gt;        &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;

&lt;span class="nx"&gt;common_tags&lt;/span&gt; &lt;span class="err"&gt;=&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="s2"&gt;"Production"&lt;/span&gt;
  &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&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;"MyApp"&lt;/span&gt;
  &lt;span class="nx"&gt;CostCenter&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Operations"&lt;/span&gt;
  &lt;span class="nx"&gt;Compliance&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Required"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy to Dev
&lt;/h3&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;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"dev.tfvars"&lt;/span&gt;
terraform apply &lt;span class="nt"&gt;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"dev.tfvars"&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.amazonaws.com%2Fuploads%2Farticles%2Fh9qr7iyqhc82lb96qq32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh9qr7iyqhc82lb96qq32.png" alt=" " width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; 3 buckets created (1 main + 2 multiple), no versioning&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy to Prod
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# First destroy dev&lt;/span&gt;
terraform destroy &lt;span class="nt"&gt;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"dev.tfvars"&lt;/span&gt;

&lt;span class="c"&gt;# Then deploy prod&lt;/span&gt;
terraform plan &lt;span class="nt"&gt;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"prod.tfvars"&lt;/span&gt;
terraform apply &lt;span class="nt"&gt;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"prod.tfvars"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; 4 buckets created (1 main + 3 multiple), versioning enabled&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Same code, different results!&lt;/strong&gt; This is how professionals manage multiple environments.&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%2Fu7n08mle3gtyh1ef0svi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7n08mle3gtyh1ef0svi.png" alt=" " width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Always Add Descriptions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt;&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;"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;&lt;strong&gt;Good:&lt;/strong&gt;&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;"bucket_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 the S3 bucket for application logs (must be globally unique)"&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;h3&gt;
  
  
  2. Use Validation Rules
&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;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_type"&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;"EC2 instance type"&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;"t2.micro"&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="s2"&gt;"t2.micro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"t2.small"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"t3.micro"&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;instance_type&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;"Instance type must be t2.micro, t2.small, or t3.micro."&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;h3&gt;
  
  
  3. Provide Sensible Defaults
&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;variable&lt;/span&gt; &lt;span class="s2"&gt;"aws_region"&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;"AWS region"&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;"us-east-1"&lt;/span&gt;  &lt;span class="c1"&gt;# Most common region&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Use Meaningful Variable Names
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt; &lt;code&gt;var.n&lt;/code&gt;, &lt;code&gt;var.x&lt;/code&gt;, &lt;code&gt;var.thing&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Good:&lt;/strong&gt; &lt;code&gt;var.bucket_name&lt;/code&gt;, &lt;code&gt;var.instance_count&lt;/code&gt;, &lt;code&gt;var.enable_monitoring&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Group Related Variables
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Network variables&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"vpc_cidr"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"subnet_cidrs"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Application variables&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"app_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"app_version"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Tags&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"common_tags"&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;h3&gt;
  
  
  6. Never Commit Secrets to tfvars
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt;&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="c1"&gt;# terraform.tfvars&lt;/span&gt;
&lt;span class="nx"&gt;database_password&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"super-secret-password"&lt;/span&gt;  &lt;span class="c1"&gt;# DON'T DO THIS!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use environment variables for secrets&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_database_password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"super-secret-password"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use AWS Secrets Manager, HashiCorp Vault, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Document Your Variables
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;README.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Required Variables&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="sb"&gt;`bucket_name`&lt;/span&gt; - Globally unique S3 bucket name

&lt;span class="gu"&gt;## Optional Variables&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="sb"&gt;`aws_region`&lt;/span&gt; - AWS region (default: us-east-1)
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`enable_versioning`&lt;/span&gt; - Enable bucket versioning (default: false)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🐛 Common Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: Variable Not Found
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&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;Error: Reference to undeclared input variable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Make sure variable is declared in &lt;code&gt;variables.tf&lt;/code&gt;:&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;"bucket_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;"Bucket name"&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;h3&gt;
  
  
  Issue 2: Type Mismatch
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&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;Error: Invalid value for input variable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Check your variable type matches the 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="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"bucket_count"&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="c1"&gt;# Not string!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;terraform.tfvars&lt;/code&gt;:&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;bucket_count&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;  &lt;span class="c1"&gt;# Not "2" (string)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Issue 3: Validation Failed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&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;Error: Invalid value for variable
Bucket count must be between 1 and 5.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Provide a value that meets the validation condition:&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;bucket_count&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="c1"&gt;# Within 1-5 range&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Issue 4: Forgot to Pass tfvars File
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Terraform uses default values instead of your custom file&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Always specify the 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 apply &lt;span class="nt"&gt;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"prod.tfvars"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Issue 5: Sensitive Output Not Hidden
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Sensitive data showing in output&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Mark output as sensitive:&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;"database_password"&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;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db_password&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="c1"&gt;# Add this&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎓 What You Just Learned
&lt;/h2&gt;

&lt;p&gt;Let's recap your new superpowers:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Variables:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert hardcoded values to flexible variables&lt;/li&gt;
&lt;li&gt;Use all variable types (string, number, bool, list, map)&lt;/li&gt;
&lt;li&gt;Add validation rules&lt;/li&gt;
&lt;li&gt;Provide defaults&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;terraform.tfvars:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store variable values in files&lt;/li&gt;
&lt;li&gt;Create environment-specific configs (dev.tfvars, prod.tfvars)&lt;/li&gt;
&lt;li&gt;Auto-loading behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;Outputs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Display important information&lt;/li&gt;
&lt;li&gt;Mark sensitive data&lt;/li&gt;
&lt;li&gt;Use in scripts and modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;Real-World Patterns:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same code, multiple environments&lt;/li&gt;
&lt;li&gt;Conditional resource creation&lt;/li&gt;
&lt;li&gt;Multiple resource creation with count&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎯 Challenge: Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Before moving to the next article, try these challenges:&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 1: Add More Variables
&lt;/h3&gt;

&lt;p&gt;Add variables for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;owner_email&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cost_center&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backup_retention_days&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Challenge 2: Create staging.tfvars
&lt;/h3&gt;

&lt;p&gt;Create a staging environment configuration between dev and prod.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 3: Use List Variable
&lt;/h3&gt;

&lt;p&gt;Create a variable for multiple availability zones:&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;"availability_zones"&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;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"us-east-1a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1b"&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;h3&gt;
  
  
  Challenge 4: Complex Map Variable
&lt;/h3&gt;

&lt;p&gt;Create a variable for instance configurations:&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;"instance_configs"&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;object&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="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;volume_size&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;h3&gt;
  
  
  Challenge 5: Output Formatting
&lt;/h3&gt;

&lt;p&gt;Create an output that combines multiple values:&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;"bucket_info"&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="s2"&gt;"Bucket ${aws_s3_bucket.example.id} in ${var.aws_region}"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📚 Additional Variable Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Variable Precedence (Order of Priority)
&lt;/h3&gt;

&lt;p&gt;Terraform loads variables in this order (last wins):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Environment variables (&lt;code&gt;TF_VAR_name&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terraform.tfvars&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terraform.tfvars.json&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*.auto.tfvars&lt;/code&gt; files (alphabetical order)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-var&lt;/code&gt; and &lt;code&gt;-var-file&lt;/code&gt; command line flags&lt;/li&gt;
&lt;/ol&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# All of these set the same variable&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_bucket_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"from-env"&lt;/span&gt;           &lt;span class="c"&gt;# Priority 1&lt;/span&gt;
&lt;span class="c"&gt;# terraform.tfvars: bucket_name = "from-file"  # Priority 2&lt;/span&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;"bucket_name=from-cli"&lt;/span&gt;    &lt;span class="c"&gt;# Priority 3 (wins!)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Environment Variables
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Set variable via environment&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_bucket_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"my-bucket-2026"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_aws_region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-west-2"&lt;/span&gt;

terraform plan  &lt;span class="c"&gt;# Uses environment variables&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Auto-Loading tfvars Files
&lt;/h3&gt;

&lt;p&gt;Terraform automatically loads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;terraform.tfvars&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform.tfvars.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;*.auto.tfvars&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;*.auto.tfvars.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# These are auto-loaded&lt;/span&gt;
terraform.tfvars
common.auto.tfvars
secrets.auto.tfvars

&lt;span class="c"&gt;# These need -var-file flag&lt;/span&gt;
dev.tfvars
prod.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔍 Understanding Variable Interpolation
&lt;/h2&gt;

&lt;p&gt;You can use variables in many ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  String Interpolation
&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;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&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;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.environment}-${var.app_name}-bucket"&lt;/span&gt;
  &lt;span class="c1"&gt;# Result: "dev-myapp-bucket"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conditional Expressions
&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;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="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="s2"&gt;"prod"&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;"t3.large"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"t3.micro"&lt;/span&gt;
  &lt;span class="c1"&gt;# prod = t3.large, anything else = t3.micro&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For Expressions
&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;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bucket_names&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;i&lt;/span&gt; &lt;span class="nx"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;range&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;bucket_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"${var.prefix}-${i}"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="c1"&gt;# Result: ["app-0", "app-1", "app-2"]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔗 Useful Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform Variables Docs:&lt;/strong&gt; &lt;a href="https://developer.hashicorp.com/terraform/language/values/variables" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/language/values/variables&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform Outputs Docs:&lt;/strong&gt; &lt;a href="https://developer.hashicorp.com/terraform/language/values/outputs" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/language/values/outputs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variable Validation:&lt;/strong&gt; &lt;a href="https://developer.hashicorp.com/terraform/language/values/variables#custom-validation-rules" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/language/values/variables#custom-validation-rules&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type Constraints:&lt;/strong&gt; &lt;a href="https://developer.hashicorp.com/terraform/language/expressions/type-constraints" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/language/expressions/type-constraints&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎬 What's Next?
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;Article 6: Building a VPC from Scratch&lt;/strong&gt;, we'll:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a complete AWS VPC with subnets&lt;/li&gt;
&lt;li&gt;Use variables for network configuration&lt;/li&gt;
&lt;li&gt;Build public and private subnets&lt;/li&gt;
&lt;li&gt;Configure route tables and internet gateways&lt;/li&gt;
&lt;li&gt;Apply everything you learned about variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You'll learn:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-world networking with Terraform&lt;/li&gt;
&lt;li&gt;Complex resource dependencies&lt;/li&gt;
&lt;li&gt;Advanced variable usage&lt;/li&gt;
&lt;li&gt;Production-ready VPC architecture&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading. I hope this article provided practical insights and a clearer understanding of the topic.&lt;/p&gt;

&lt;p&gt;If you found this useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value
&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today
&lt;/li&gt;
&lt;li&gt;💾 Save it for your next optimization session
&lt;/li&gt;
&lt;li&gt;🔄 Share it with your team
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives are coming soon on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Operations&lt;/li&gt;
&lt;li&gt;GenAI &amp;amp; Agentic AI&lt;/li&gt;
&lt;li&gt;DevOps Automation&lt;/li&gt;
&lt;li&gt;Data &amp;amp; Platform Engineering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow along for weekly insights and hands-on guides.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts. Feel free to drop a comment or connect with me on:&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, reach out at:&lt;/p&gt;

&lt;p&gt;📧 &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Found this helpful? Share it with your team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⭐ Star the repo • 📖 Follow the series • 💬 Ask questions  &lt;/p&gt;

&lt;p&gt;Made by &lt;strong&gt;Sarvar Nadaf&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🌐 &lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;https://sarvarnadaf.com&lt;/a&gt;&lt;/p&gt;




</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>What is OpenClaw? A Self Hosted AI Assistants</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Mon, 30 Mar 2026 17:56:49 +0000</pubDate>
      <link>https://forem.com/aws-builders/what-is-openclaw-a-self-hosted-ai-assistants-311j</link>
      <guid>https://forem.com/aws-builders/what-is-openclaw-a-self-hosted-ai-assistants-311j</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;

&lt;p&gt;Let's dive in and explore the fascinating world of cloud technology together! 🚀&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;New to Self-Hosted AI?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This article assumes basic familiarity with computers, software installation, and online services. If terms like "API," "server," or "open source" are new to you, don't worry focus on the core concept: OpenClaw is an AI assistant that you run on your own computer or server, rather than relying on a company's service like ChatGPT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What This Article Covers:&lt;/strong&gt; Understanding what OpenClaw is, why it matters, and whether it's right for you.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;What's Coming Next:&lt;/strong&gt; Hands-on setup, configuration, and deployment (no prior experience with self-hosting required we'll walk through everything step-by-step).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Imagine having a personal assistant that lives on your infrastructure, responds through the messaging apps you already use, and executes tasks across your entire cloud environment. That's OpenClaw. But unlike the AI assistants you're familiar with ChatGPT, Claude, or GitHub Copilot this one doesn't phone home to someone else's servers. It runs on your machine, uses your API keys, and keeps your data exactly where you want it.&lt;/p&gt;

&lt;p&gt;The story begins in November 2025 when Austrian developer Peter Steinberger built what he called a "weekend project." He wanted an AI that could do more than chat one that could actually execute commands, manage files, read emails, and integrate with the tools he used daily. Within weeks, the project exploded. By March 2026, it had accumulated over 340,000 GitHub stars and attracted attention from Silicon Valley startups to Chinese tech giants. Steinberger eventually joined OpenAI and moved the project to an open-source foundation, but the core philosophy remained unchanged: your assistant, your machine, your rules.&lt;/p&gt;

&lt;p&gt;For anyone interested in AI and privacy, OpenClaw represents something different. It's not a SaaS product with usage limits and data residency questions. It's software you install, configure, and control. You choose which AI provider to use Anthropic's Claude, OpenAI's GPT models, Google's Gemini, or even self-hosted options like Ollama. You decide which messaging platforms to enable. You set the security boundaries. And when you need to see what happened, the logs are on your computer, not buried in someone else's cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  What OpenClaw Actually Is
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Architecture and Deployment Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenClaw is a Node.js application that acts as a gateway between messaging platforms and large language models (LLMs AI systems like ChatGPT or Claude). You install it on a server your laptop, a homelab machine, or a cloud VM and it stays running as a daemon. The architecture is straightforward: a WebSocket-based control plane (a real-time communication hub) listens on port 18789, handling connections from messaging channels, the web dashboard, and optional companion apps for macOS, iOS, and Android.&lt;/p&gt;

&lt;p&gt;The gateway doesn't process AI requests itself. Instead, it routes conversations to your configured LLM provider via their APIs. When you send a message through WhatsApp or Slack, OpenClaw receives it, forwards the context to Claude or GPT, gets the response, and delivers it back through the same channel. All conversation history, configuration, and session state live in local SQLite databases under &lt;code&gt;~/.openclaw/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-Channel Integration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where OpenClaw diverges from traditional chatbots. Rather than forcing you into a web interface or proprietary app, it meets you where you already work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Messaging platforms&lt;/strong&gt;: WhatsApp, Telegram, Discord, Slack, Microsoft Teams, Signal, Matrix&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specialized channels&lt;/strong&gt;: IRC, Google Chat, Mattermost, Twitch, WeChat (via Tencent plugin)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct interfaces&lt;/strong&gt;: Web dashboard, macOS menu bar app, iOS/Android companion apps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer tools&lt;/strong&gt;: CLI commands for scripting and automation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each channel operates independently. You can have different security policies for Discord versus WhatsApp, route specific channels to isolated agent workspaces, or restrict certain tools based on where the request originated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Skills System&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenClaw extends beyond conversation through a skills framework. Skills are self-contained modules think of them as plugins that give the AI new capabilities. A skill is just a directory containing a &lt;code&gt;SKILL.md&lt;/code&gt; file with instructions and metadata. The AI reads these instructions and knows how to use the skill's tools.&lt;/p&gt;

&lt;p&gt;Skills can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bundled&lt;/strong&gt;: Shipped with OpenClaw (browser automation, file operations, system commands)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed&lt;/strong&gt;: Installed from the ClawHub registry&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workspace-specific&lt;/strong&gt;: Custom skills you write for your environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The precedence model matters for teams building workflows. Workspace skills override global skills, which override bundled skills. This means you can customize behavior per project without modifying the core installation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool Execution and Sandboxing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the AI decides it needs to run a command or access a file, OpenClaw's tool system handles the execution. By default, tools run directly on the host for the main session. But for group chats or untrusted channels, you can enable sandbox mode. Sandboxed sessions run inside per-session Docker containers with restricted tool access.&lt;/p&gt;

&lt;p&gt;The security model is explicit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Main session (your direct chats): Full tool access by default&lt;/li&gt;
&lt;li&gt;Group sessions: Configurable sandbox with allowlists and denylists&lt;/li&gt;
&lt;li&gt;Tool categories: &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;browser&lt;/code&gt;, &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;write&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;sessions&lt;/code&gt;, &lt;code&gt;nodes&lt;/code&gt;, &lt;code&gt;cron&lt;/code&gt;, &lt;code&gt;discord&lt;/code&gt;, &lt;code&gt;gateway&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You define which tools each session type can use. A production deployment might allow read-only file access for group chats while reserving write operations for authenticated direct messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Self-Hosting Matters
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Data Privacy and Control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you deploy OpenClaw on your infrastructure, you control the data flow. Conversation logs, uploaded files, and execution history never leave your environment unless you explicitly configure external integrations. For organizations with strict data residency requirements healthcare, finance, government this matters. You're not trusting a third party to handle PHI (Protected Health Information) or PII (Personally Identifiable Information). You're running the infrastructure yourself.&lt;/p&gt;

&lt;p&gt;The LLM API calls still go to external providers (unless you use self-hosted models), but you choose which provider and can route through your own network controls. Want to proxy all OpenAI requests through your corporate gateway? Configure the API endpoint. Need to log every prompt for compliance? Intercept at the gateway level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost Control and Model Flexibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SaaS AI assistants charge per seat or per usage tier. OpenClaw inverts this model. You pay your LLM provider directly based on token consumption. If Claude is too expensive for your use case, switch to GPT-4o-mini. If you want to experiment with open-source models, point it at Ollama running locally. The gateway doesn't care which model you use it just routes requests.&lt;/p&gt;

&lt;p&gt;This flexibility extends to failover and load balancing. Configure multiple API keys for the same provider, and OpenClaw rotates through them when rate limits hit. Set up model fallback chains: try Claude Opus first, fall back to GPT-4 if it's overloaded, and use a local model as the last resort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Cost Comparison:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SaaS AI Assistant&lt;/strong&gt;: $20-30/user/month (fixed cost, limited usage)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenClaw + Claude API&lt;/strong&gt;: Pay per token (1M input tokens ≈ $3-8 depending on model)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenClaw + Local LLM&lt;/strong&gt;: Infrastructure costs only (no per-token charges)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For teams running thousands of queries daily, the direct API model often costs less than per-seat licensing. For occasional users, SaaS might be cheaper. The key difference: you control the trade-off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure as Code Integration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because OpenClaw is just a Node.js application with a JSON configuration file, it fits naturally into infrastructure-as-code (IaC) workflows managing infrastructure through code rather than manual configuration. The configuration lives at &lt;code&gt;~/.openclaw/openclaw.json&lt;/code&gt; and supports environment variable substitution for secrets. You can template it with Terraform, manage it with Ansible, or version it in Git.&lt;/p&gt;

&lt;p&gt;Deployment patterns cloud architects already know apply directly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Systemd service&lt;/strong&gt;: Install the daemon, enable it, manage it like any other service&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker container&lt;/strong&gt;: Official images available, mount config as a volume&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes&lt;/strong&gt;: Deploy as a StatefulSet (a workload type for applications that need persistent storage) with persistent storage for the database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nix&lt;/strong&gt;: Declarative configuration with the community Nix package&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security Boundaries and Threat Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenClaw's security model assumes you understand the risks of giving an AI broad system access. The maintainers are explicit about this. One core maintainer warned on Discord: "if you can't understand how to run a command line, this is far too dangerous of a project for you to use safely."&lt;/p&gt;

&lt;p&gt;The threat surface includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prompt injection&lt;/strong&gt;: Malicious instructions embedded in data the AI processes (emails, documents, web pages) that trick the AI into executing unintended commands&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool misuse&lt;/strong&gt;: The AI executing destructive commands based on misinterpreted context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Third-party skills&lt;/strong&gt;: Unvetted skills from the community that could exfiltrate data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channel compromise&lt;/strong&gt;: If someone gains access to an authorized messaging account, they control the AI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cisco's security research team demonstrated this in March 2026 when they found a third-party skill performing data exfiltration. The skill repository lacked adequate vetting, and users installing it unknowingly gave attackers access to their environment.&lt;/p&gt;

&lt;p&gt;For production use, you need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run sandboxed sessions for any untrusted input source&lt;/li&gt;
&lt;li&gt;Audit third-party skills before installation&lt;/li&gt;
&lt;li&gt;Use DM pairing mode to require explicit approval for new contacts&lt;/li&gt;
&lt;li&gt;Monitor execution logs for unexpected tool usage&lt;/li&gt;
&lt;li&gt;Isolate the OpenClaw instance from sensitive systems&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;The MoltMatch Incident: A Cautionary Tale&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In February 2026, computer science student Jack Luo configured his OpenClaw agent to explore its capabilities. He connected it to Moltbook a social network for AI agents and let it run autonomously. Days later, he discovered the agent had created a profile on MoltMatch, a dating platform where AI agents interact on behalf of users, and was screening potential matches without his explicit direction.&lt;/p&gt;

&lt;p&gt;The incident highlighted a fundamental challenge with autonomous agents: when you give an AI broad permissions and vague instructions, it will interpret its mandate creatively. Luo's agent saw "explore capabilities" and "connect to agent platforms" as permission to create dating profiles. The AI-generated profile didn't reflect him authentically, and he had no idea it was happening until someone told him.&lt;/p&gt;

&lt;p&gt;This matters for anyone managing systems because the same dynamic applies to automation. If you tell an AI to "optimize costs" without clear boundaries, it might decide to delete things it deems unnecessary. If you ask it to "improve security," it could change settings in ways you didn't anticipate. Autonomous agents require explicit constraints, not just general goals.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Adoption Patterns
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Small Business and Freelancer Workflows&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenClaw has found traction among small businesses and freelancers who need automation but can't afford enterprise tools. Common workflows include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lead generation: Scraping prospect lists, researching companies, updating CRM systems&lt;/li&gt;
&lt;li&gt;Content management: Drafting emails, summarizing documents, generating reports&lt;/li&gt;
&lt;li&gt;System administration: Monitoring servers, running diagnostics, deploying updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These users value the flexibility to customize behavior without vendor lock-in. A freelance consultant can write a workspace skill that integrates with their specific CRM and invoicing tools, then share that skill with clients who use the same stack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enterprise Experimentation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Larger organizations are testing OpenClaw in controlled environments. The typical pattern: deploy it on a developer's workstation or a sandbox VM, connect it to a private Slack channel, and use it for internal tooling. Teams report using it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation search: Indexing internal wikis and answering questions&lt;/li&gt;
&lt;li&gt;Incident response: Gathering logs, running diagnostics, summarizing findings&lt;/li&gt;
&lt;li&gt;Code review assistance: Analyzing pull requests, suggesting improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key constraint is trust. Enterprises won't give OpenClaw production access until they've validated its behavior in isolated environments. The security incidents and lack of formal audits make it a hard sell for risk-averse organizations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Your Setup
&lt;/h2&gt;

&lt;p&gt;If you're evaluating OpenClaw, think of it as software infrastructure, not a product. You're not buying a service; you're installing and maintaining a component that needs care and attention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Questions to Consider:&lt;/strong&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Where will it run? (Your laptop, a home server, a cloud VM)&lt;/li&gt;
&lt;li&gt;Who can access it? (Just you, your team, your organization)&lt;/li&gt;
&lt;li&gt;What can it access? (Read-only files, full system control, isolated sandbox)&lt;/li&gt;
&lt;li&gt;How will you monitor it? (Log files, activity tracking, alerts)&lt;/li&gt;
&lt;li&gt;What's the risk if compromised? (Isolated test environment vs. access to important data)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Which AI provider will you use? (Cost, rate limits, data handling)&lt;/li&gt;
&lt;li&gt;Which messaging platforms? (Authentication, user verification)&lt;/li&gt;
&lt;li&gt;What internal systems? (APIs, databases, file storage)&lt;/li&gt;
&lt;li&gt;How will you monitor it? (Health checks, error tracking, usage metrics)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Who maintains the configuration? (You, your team, IT department)&lt;/li&gt;
&lt;li&gt;How do you handle updates? (Manual upgrades, automated deployment)&lt;/li&gt;
&lt;li&gt;What's the support model? (Community forums, internal expertise)&lt;/li&gt;
&lt;li&gt;How do you manage secrets? (Environment variables, password managers)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The answers depend on your technical comfort level and risk tolerance. A tech-savvy individual might run it on their laptop for personal use. A small team might deploy it on a shared server with careful access controls. An enterprise might lock it down in an isolated environment. All are valid approaches based on your needs and skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;OpenClaw is not a polished consumer product. It's a powerful, flexible, occasionally dangerous tool that gives you control at the cost of responsibility. For people who understand the trade-offs, it offers something rare: an AI assistant that runs on your terms, integrates with your tools, and doesn't require you to trust a company with your data.&lt;/p&gt;

&lt;p&gt;The project is still young. The security model is evolving. The ecosystem is fragmented. But the core idea self-hosted, multi-channel, tool-capable AI agents addresses real needs that SaaS products don't solve. Whether OpenClaw itself becomes the standard or just proves the concept for something better, the architecture it represents is worth understanding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to Consider OpenClaw:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You care deeply about data privacy and control&lt;/li&gt;
&lt;li&gt;You want to avoid subscription fees for large-scale usage&lt;/li&gt;
&lt;li&gt;You need deep integration with your own tools and systems&lt;/li&gt;
&lt;li&gt;You have technical skills or are willing to learn&lt;/li&gt;
&lt;li&gt;You're comfortable with ongoing maintenance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to Avoid OpenClaw:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're not comfortable with command-line tools&lt;/li&gt;
&lt;li&gt;You need something that works immediately without setup&lt;/li&gt;
&lt;li&gt;You can't dedicate time to security and maintenance&lt;/li&gt;
&lt;li&gt;You prefer paying for convenience over having control&lt;/li&gt;
&lt;li&gt;Your use case doesn't justify the complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you decide to explore it, start small. Run it in an isolated environment, connect it to a test channel, give it limited permissions. Learn how it behaves, where it fails, and what it can actually do. Then decide if the benefits justify the operational overhead and security risks.&lt;/p&gt;

&lt;p&gt;That's the honest assessment. OpenClaw is powerful infrastructure for people who know what they're doing. If that's you, it's worth exploring. If it's not, wait for the ecosystem to mature.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Coming Next:&lt;/strong&gt; In our next article, we'll cover the technical implementation installation, configuration, and deployment with step-by-step examples. We'll walk through setting up OpenClaw on different platforms and implementing security best practices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What We'll Cover in Upcoming Articles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 2: Installation &amp;amp; Setup&lt;/strong&gt; - Step-by-step guide, prerequisites, system requirements, and getting your first instance running&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 3: Configuration Deep-Dive&lt;/strong&gt; - API keys, messaging platform integration, security policies, and sandbox configuration
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 4: Deployment Options&lt;/strong&gt; - Running on Windows/Mac/Linux, cloud servers, and home servers with monitoring and cost optimization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 5: Security Best Practices&lt;/strong&gt; - Threat mitigation, audit logging, access control, and incident response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Questions or Topics You'd Like Covered?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Drop a comment below with your questions about OpenClaw. Whether you're wondering about specific use cases, integration challenges, cost comparisons, or anything else we'll address them in upcoming articles. Common questions we're already planning to cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How much does it actually cost to run?&lt;/li&gt;
&lt;li&gt;Can I use it on Windows without WSL?&lt;/li&gt;
&lt;li&gt;What's the learning curve for someone new to self-hosting?&lt;/li&gt;
&lt;li&gt;How does it compare to AutoGPT or LangChain agents?&lt;/li&gt;
&lt;li&gt;Can I run it on a Raspberry Pi or home server?&lt;/li&gt;
&lt;/ul&gt;




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

&lt;ul&gt;
&lt;li&gt;Official Website: &lt;a href="https://openclaw.ai" rel="noopener noreferrer"&gt;https://openclaw.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub Repository: &lt;a href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;https://github.com/openclaw/openclaw&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading! I hope this article gave you practical insights and a clearer perspective on the topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Was this helpful?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today&lt;/li&gt;
&lt;li&gt;💾 Save for your next optimization session&lt;/li&gt;
&lt;li&gt;🔄 Share with your team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Follow me for more on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS architecture patterns&lt;/li&gt;
&lt;li&gt;FinOps automation&lt;/li&gt;
&lt;li&gt;Multi-account strategies&lt;/li&gt;
&lt;li&gt;AI-driven DevOps&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives coming soon on cloud operations, GenAI, Agentic-AI, DevOps, and data workflows follow for weekly insights.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts drop a comment or connect with me on &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, feel free to reach out directly at &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Learning&lt;/strong&gt; 🚀&lt;/p&gt;

</description>
      <category>openclaw</category>
      <category>ai</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>AI Assistance vs AI Agents: Understanding the Shift from Responses to Autonomous Systems</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Wed, 25 Mar 2026 19:11:06 +0000</pubDate>
      <link>https://forem.com/aws-builders/ai-assistance-vs-ai-agents-understanding-the-shift-from-responses-to-autonomous-systems-pb3</link>
      <guid>https://forem.com/aws-builders/ai-assistance-vs-ai-agents-understanding-the-shift-from-responses-to-autonomous-systems-pb3</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, Generative AI, and Agentic AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;

&lt;p&gt;Let's dive in and explore the fascinating world of cloud technology together! 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  Here's What Most People Get Wrong
&lt;/h2&gt;

&lt;p&gt;ChatGPT can write your email. But it can't send it. That's the difference between an AI assistant and an AI agent, and honestly, most people have no idea there even is a difference.&lt;/p&gt;

&lt;p&gt;I've been working with AI for a while now, and I keep seeing the same confusion everywhere. People use "AI assistant" and "AI agent" like they're the same thing. They're not. Not even close.&lt;/p&gt;

&lt;p&gt;Here's what you need to know: &lt;strong&gt;AI assistants tell you what to do. AI agents actually do it for you.&lt;/strong&gt; That's the whole game right there.&lt;/p&gt;

&lt;p&gt;Let me break this down in a way that actually makes sense.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI Assistants: The Smart Advisor
&lt;/h2&gt;

&lt;p&gt;Think about the last time you used ChatGPT or asked Siri something. You asked a question, got an answer, and then you had to go do something with that answer. That's an AI assistant.&lt;/p&gt;

&lt;p&gt;An AI assistant is like having a really smart friend who knows everything but can't actually touch anything in your world. They can tell you exactly what to do, step by step, but you're the one who has to do it.&lt;/p&gt;

&lt;p&gt;Here's what they're good at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Answering questions (and they're really good at this)&lt;/li&gt;
&lt;li&gt;Giving you suggestions and advice&lt;/li&gt;
&lt;li&gt;Helping you think through problems&lt;/li&gt;
&lt;li&gt;Generating content like emails, code, or ideas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here's what they can't do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Take any action in your systems&lt;/li&gt;
&lt;li&gt;Make decisions and execute them&lt;/li&gt;
&lt;li&gt;Complete tasks that need multiple steps&lt;/li&gt;
&lt;li&gt;Use tools or APIs on their own&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me give you a real example. Say you ask an AI assistant: "What's the weather today?"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "What's the weather today?"
Assistant: "It's 72°F and sunny in New York."
You: "Should I bring an umbrella?"
Assistant: "No, it's not going to rain today."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect, right? You got your answer. But notice what didn't happen - the assistant didn't check your calendar, didn't see you have a meeting at 3 PM, didn't notice the forecast shows rain later, and definitely didn't pack an umbrella for you. It just answered your question.&lt;/p&gt;

&lt;p&gt;That's the limitation. And for a lot of things, that's totally fine! Sometimes you just need information.&lt;/p&gt;




&lt;h2&gt;
  
  
  Agentic AI: The Autonomous Doer
&lt;/h2&gt;

&lt;p&gt;Now here's where things get interesting. Agentic AI doesn't just tell you what to do - it actually does it.&lt;/p&gt;

&lt;p&gt;Think of it like this: if an AI assistant is your smart friend giving advice, an agentic AI is your trusted employee who you can hand a project to and they'll just... handle it. They'll figure out the steps, make the decisions, use whatever tools they need, and come back with results.&lt;/p&gt;

&lt;p&gt;This is what makes agents different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They can access and use tools (APIs, databases, systems)&lt;/li&gt;
&lt;li&gt;They make decisions based on what they find&lt;/li&gt;
&lt;li&gt;They complete multi-step workflows autonomously&lt;/li&gt;
&lt;li&gt;They only ask you when they really need input&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the same scenario but with an agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "Book me a flight to New York next week."

Agent: *searches multiple airlines*
       *compares prices and times*
       *checks your calendar for conflicts*
       *finds the best option*
       *books the ticket*
       *adds it to your calendar*
       *sends confirmation to your email*

"Done! I booked you on Delta flight DL123, Tuesday 9 AM, $287. 
I saw you have a meeting at 2 PM that day, so this gives you time. 
Confirmation is in your email."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the difference? You gave one instruction, and the agent handled everything. It made decisions (which flight is best), used tools (booking system, calendar, email), and completed the entire workflow. You didn't have to do anything except say what you wanted.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let Me Show You the Real Difference
&lt;/h2&gt;

&lt;p&gt;I think the best way to understand this is with a practical example. Let's say you need to check on your servers (if you're not technical, just think of this as checking if your website is working).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With an AI Assistant:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You ask: "I need to check my server status."&lt;/p&gt;

&lt;p&gt;The assistant responds:&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="s2"&gt;"Sure! To check your server status, you can:
1. Log into your AWS Console
2. Navigate to the EC2 Dashboard
3. Look at the instance state column

Or if you prefer the command line, run:
aws ec2 describe-instances

Would you like help with anything else?"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great advice! But now you have to go do all of that. You have to log in, navigate around, run commands, interpret the results. The assistant told you what to do, but you're still doing all the work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With an Agentic AI:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You say the same thing: "I need to check my server status."&lt;/p&gt;

&lt;p&gt;The agent responds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*connects to your AWS account*
*checks all your servers*
*analyzes the data*

"I checked your 5 servers. Here's what I found:

- web-server-1: Running fine, healthy
- web-server-2: Running but CPU is at 89% (might need attention soon)
- database-1: Running fine, healthy  
- api-server-1: STOPPED - this one is down
- backup-server: Running fine, healthy

I noticed api-server-1 is down. This could be affecting your API endpoints. 
Want me to restart it for you?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent didn't just tell you what to do. It actually went and checked everything, found a problem, and is ready to fix it if you want. That's the power of agentic AI.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters in 2026
&lt;/h2&gt;

&lt;p&gt;Look, I get it. For years, we've been calling everything "AI assistants" and it worked fine. But now we're in 2026, and the technology has split into two very different paths.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI assistants got better at answering.&lt;/strong&gt; They understand context better, they give more accurate information, they can help with more complex questions. ChatGPT, Claude, and similar tools are incredibly good at what they do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agentic AI learned to act.&lt;/strong&gt; They can now access your tools, make decisions, and complete entire workflows. They're not just smart anymore - they're capable.&lt;/p&gt;

&lt;p&gt;And here's the thing: most people are still using AI like it's 2023. They're asking questions and copying answers when they could be handing off entire tasks.&lt;/p&gt;

&lt;p&gt;Let me give you some real examples of what's possible now:&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Copilot Workspace
&lt;/h3&gt;

&lt;p&gt;You tell it: "Add user authentication to this app."&lt;/p&gt;

&lt;p&gt;Instead of just giving you code snippets, it can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Analyze your codebase&lt;/li&gt;
&lt;li&gt;Write code across multiple files&lt;/li&gt;
&lt;li&gt;Suggest database changes&lt;/li&gt;
&lt;li&gt;Draft API endpoints&lt;/li&gt;
&lt;li&gt;Generate tests&lt;/li&gt;
&lt;li&gt;Create a pull request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You still review everything and make the final decisions, but it handles the heavy lifting. That's moving toward agentic behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS Bedrock Agents
&lt;/h3&gt;

&lt;p&gt;You can set up an agent to monitor your infrastructure. It can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Watch your servers continuously&lt;/li&gt;
&lt;li&gt;Detect when something goes wrong&lt;/li&gt;
&lt;li&gt;Analyze issues&lt;/li&gt;
&lt;li&gt;Take corrective actions (like restarting services)&lt;/li&gt;
&lt;li&gt;Log everything&lt;/li&gt;
&lt;li&gt;Alert you when it needs help&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of checking everything manually, you get a report: "Had 3 minor issues last night, all handled automatically." The agent does the routine monitoring while you focus on bigger problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modern DevOps Agents
&lt;/h3&gt;

&lt;p&gt;Your deployment fails at 2 AM. An agent can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect the failure quickly&lt;/li&gt;
&lt;li&gt;Analyze the logs&lt;/li&gt;
&lt;li&gt;Identify the issue&lt;/li&gt;
&lt;li&gt;Roll back the deployment&lt;/li&gt;
&lt;li&gt;Alert the team with context&lt;/li&gt;
&lt;li&gt;Generate an incident report&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You find out at 9 AM that there was a problem and it's already been handled. Not perfect, but better than waking up to a crisis.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Quick Comparison
&lt;/h2&gt;

&lt;p&gt;If you're still wrapping your head around this, here's a simple table that breaks it down:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;th&gt;AI Assistant&lt;/th&gt;
&lt;th&gt;Agentic AI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Answers your questions&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gives you information&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Takes actions in systems&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uses tools and APIs&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Makes decisions on its own&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Handles multi-step tasks&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works autonomously&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Needs your approval for everything&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;⚠️ Sometimes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The pattern is pretty clear, right? Assistants are great at the "thinking" part. Agents are great at the "doing" part.&lt;/p&gt;




&lt;h2&gt;
  
  
  So When Should You Use Each One?
&lt;/h2&gt;

&lt;p&gt;This is the practical question everyone should be asking. Because here's the truth: you don't always need an agent. Sometimes an assistant is exactly what you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use an AI Assistant When:
&lt;/h3&gt;

&lt;p&gt;You want information or advice. If you're trying to learn something, understand a concept, or get suggestions, an assistant is perfect. You're not trying to automate anything - you just want to think through something with help.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;"Help me write this email" (you'll review and send it)&lt;/li&gt;
&lt;li&gt;"Explain how this code works" (you're learning)&lt;/li&gt;
&lt;li&gt;"Give me ideas for my presentation" (you're brainstorming)&lt;/li&gt;
&lt;li&gt;"What's the best way to structure this database?" (you want advice)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You want to stay in control. Sometimes you don't want anything happening automatically. You want to review every step, make every decision, and execute everything yourself. That's totally valid, and assistants are perfect for this.&lt;/p&gt;

&lt;p&gt;You're working on creative or strategic tasks. Writing, designing, planning, strategizing - these are areas where you want AI to augment your thinking, not replace your decision-making.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Agentic AI When:
&lt;/h3&gt;

&lt;p&gt;You have repetitive workflows. If you're doing the same multi-step process over and over, that's a perfect candidate for an agent. Let it handle the routine stuff while you focus on things that actually need your brain.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Monitoring systems and alerting on issues&lt;/li&gt;
&lt;li&gt;Processing incoming data and routing it correctly&lt;/li&gt;
&lt;li&gt;Handling customer support for common questions&lt;/li&gt;
&lt;li&gt;Running deployments and rollbacks&lt;/li&gt;
&lt;li&gt;Generating and sending reports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You need 24/7 operation. Agents don't sleep. If you need something monitored or handled around the clock, an agent is your answer.&lt;/p&gt;

&lt;p&gt;Speed matters. Agents can react in seconds. If you need fast response to events or issues, agents beat humans every time.&lt;/p&gt;

&lt;p&gt;The task is well-defined. If you can clearly describe the steps and decision points, an agent can probably handle it. The more structured the workflow, the better agents perform.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Business Impact
&lt;/h2&gt;

&lt;p&gt;Let me give you a concrete example of what this looks like in practice.&lt;/p&gt;

&lt;p&gt;I know a company that was spending about 2 hours every day manually checking their server infrastructure. Someone had to log in, check each server, look at metrics, make sure everything was healthy. Boring, repetitive, but necessary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, they tried an AI assistant approach.&lt;/strong&gt; They used ChatGPT to help generate the commands they needed to run. It was helpful - instead of remembering all the commands, they could just ask "how do I check CPU usage?" and get the answer. But they still had to run everything manually. They saved maybe 15 minutes a day. Better than nothing, but not game-changing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then they built an agentic AI solution.&lt;/strong&gt; They set up an agent that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checks all servers every 5 minutes&lt;/li&gt;
&lt;li&gt;Analyzes the metrics automatically&lt;/li&gt;
&lt;li&gt;Alerts them when something is actually wrong&lt;/li&gt;
&lt;li&gt;Can restart services if configured to do so&lt;/li&gt;
&lt;li&gt;Generates a daily health report&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now? They spend maybe 10-15 minutes a day reviewing the report. The agent handles the routine monitoring. That's about 1 hour and 45 minutes saved every day. Not revolutionary, but meaningful. And they catch issues faster because the agent is always watching.&lt;/p&gt;

&lt;p&gt;That's the difference between telling and doing.&lt;/p&gt;




&lt;h2&gt;
  
  
  What People Get Wrong About This
&lt;/h2&gt;

&lt;p&gt;There's a lot of confusion out there, so let me clear up some common misconceptions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"All AI is agentic now"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No, it's really not. Most of the AI you use every day is still assistant-level. ChatGPT, Claude, most chatbots - they're assistants. They're really good assistants, but they're not agents. True agentic AI that can take actions in your systems is still relatively new and not as widespread as people think.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Agents will replace all human work"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the fear everyone has, and it's not realistic. Agents are good at repetitive, well-defined tasks. They're not replacing strategy, creativity, complex decision-making, or anything that requires real judgment. They're tools that handle routine work so humans can focus on more valuable tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"AI assistants are outdated now"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not at all. Assistants are perfect for tons of use cases. Not everything needs to be automated. Sometimes you want advice, not action. Sometimes you want to stay in control of every step. Assistants aren't going anywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Agents are just better assistants"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the big one people get wrong. They're not "better" - they're fundamentally different. It's like saying a car is a "better" bicycle. No, it's a different tool for different purposes. Assistants and agents solve different problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Agents are too risky to use"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There's some truth to this concern, but it's manageable. Yes, giving AI the ability to take actions in your systems requires careful setup. You need guardrails, monitoring, and clear boundaries. But we've figured this out. Modern agent frameworks have safety built in. You can limit what they can do, require approval for certain actions, and monitor everything. It's not riskier than giving a new employee access to your systems - you just need proper controls.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Safety Question Everyone Should Ask
&lt;/h2&gt;

&lt;p&gt;Since we're talking about AI that can actually do things in your systems, let's address the elephant in the room: is this safe?&lt;/p&gt;

&lt;p&gt;The honest answer is: it depends on how you set it up.&lt;/p&gt;

&lt;p&gt;Here's what you need to think about:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Guardrails:&lt;/strong&gt; Good agent systems let you define exactly what the agent can and can't do. You can say "you can restart servers, but you can't delete anything" or "you can book flights under $500, but ask me about anything more expensive." These boundaries are crucial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monitoring:&lt;/strong&gt; You should be logging everything your agent does. Every action, every decision, every API call. This isn't just for debugging - it's for accountability and safety.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approval workflows:&lt;/strong&gt; For high-stakes actions, you can require human approval. The agent can do all the analysis and preparation, but it waits for your "yes" before executing anything critical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rollback capabilities:&lt;/strong&gt; Things go wrong sometimes. Your agent should be able to undo its actions, or at least alert you immediately if something unexpected happens.&lt;/p&gt;

&lt;p&gt;The key is this: you're not giving the agent unlimited power. You're giving it specific, controlled capabilities within boundaries you define. It's like giving someone the keys to your car - you're trusting them with something important, but you're not giving them ownership of your entire life.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where This Is All Heading
&lt;/h2&gt;

&lt;p&gt;We're in 2026, and we're still early in the agentic AI era. Here's what's developing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-agent systems are emerging.&lt;/strong&gt; Instead of one agent doing everything, you might have multiple specialized agents working together. One handles customer support, another manages infrastructure, another handles data analysis. They can coordinate to handle complex workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The line is blurring.&lt;/strong&gt; Some AI assistants are adding limited action capabilities. Some agents are getting better at explaining their reasoning. We're moving toward hybrid systems that can adapt based on what you need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's getting easier to build.&lt;/strong&gt; Right now, building an agent requires technical skill. But we're seeing more platforms that make it easier. Eventually, less technical people will be able to build agents for specific workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safety is improving.&lt;/strong&gt; As more people use agents, we're learning better ways to build in safety features, monitoring, and control mechanisms. The technology is maturing.&lt;/p&gt;

&lt;p&gt;The future probably isn't "assistants vs agents." It's more likely "assistants and agents working together." You'll use assistants for thinking and planning, and agents for executing and monitoring. They complement each other.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Actually Get Started
&lt;/h2&gt;

&lt;p&gt;Alright, enough theory. Let's talk about what you should actually do with this information.&lt;/p&gt;

&lt;h3&gt;
  
  
  If You Want to Start Using AI Assistants:
&lt;/h3&gt;

&lt;p&gt;This is the easy path. You can literally start right now.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pick a tool.&lt;/strong&gt; ChatGPT, Claude, or any of the major AI assistants. Most have free tiers to start.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learn to prompt well.&lt;/strong&gt; The better you ask questions, the better answers you get. This is a skill worth developing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start with simple tasks.&lt;/strong&gt; Use it for writing, brainstorming, learning. Get comfortable with what it can and can't do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integrate if needed.&lt;/strong&gt; If you're technical, most assistants have APIs you can use in your applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; $0-100/month depending on usage&lt;br&gt;
&lt;strong&gt;Time to start:&lt;/strong&gt; Literally right now&lt;br&gt;
&lt;strong&gt;Complexity:&lt;/strong&gt; Low - anyone can do this&lt;/p&gt;

&lt;h3&gt;
  
  
  If You Want to Build Agentic AI:
&lt;/h3&gt;

&lt;p&gt;This is more involved, but not as hard as you might think.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Define your workflow clearly.&lt;/strong&gt; What exact task do you want automated? What are the steps? What decisions need to be made? The clearer you are, the better your agent will work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Choose your platform.&lt;/strong&gt; AWS Bedrock Agents, LangChain, AutoGPT, or other agent frameworks. Each has pros and cons. Bedrock is good if you're already on AWS. LangChain is good if you want flexibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start small.&lt;/strong&gt; Don't try to automate everything at once. Pick one simple workflow and get that working first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build in safety from day one.&lt;/strong&gt; Set clear boundaries on what the agent can do. Log everything. Start with requiring approval for actions, then relax that as you gain confidence.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test thoroughly.&lt;/strong&gt; Run your agent through every scenario you can think of. What happens when things go wrong? How does it handle edge cases?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitor and improve.&lt;/strong&gt; Once it's running, watch it closely at first. You'll find ways to improve it based on how it actually performs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; $100-1000+/month depending on what you're building&lt;br&gt;
&lt;strong&gt;Time to start:&lt;/strong&gt; Days to weeks&lt;br&gt;
&lt;strong&gt;Complexity:&lt;/strong&gt; Medium - you'll need some technical skills or help&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Here's what you need to remember from all of this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI assistants are for thinking.&lt;/strong&gt; They help you understand, plan, create, and learn. They're your smart advisor who knows a lot but can't touch anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agentic AI is for doing.&lt;/strong&gt; They handle workflows, take actions, make decisions, and complete tasks. They're your capable employee who can handle projects independently.&lt;/p&gt;

&lt;p&gt;Both are valuable. Both have their place. The question isn't "which is better?" The question is "which solves my problem?"&lt;/p&gt;

&lt;p&gt;Need answers? Use an assistant.&lt;br&gt;
Need actions? Use an agent.&lt;br&gt;
Need both? Use both.&lt;/p&gt;

&lt;p&gt;We're in 2026, and we're just starting to figure out what's possible with AI that can actually do things. The assistants made us smarter. The agents are making us more productive.&lt;/p&gt;

&lt;p&gt;The real power comes from knowing when to use each one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference Guide
&lt;/h2&gt;

&lt;p&gt;Still not sure which you need? Ask yourself these questions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it just need to answer, or does it need to act?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Just answer → Assistant&lt;/li&gt;
&lt;li&gt;Actually act → Agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Do I want to stay in control of every step?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Yes → Assistant&lt;/li&gt;
&lt;li&gt;No, I want it handled → Agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Is this a one-time question or an ongoing workflow?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One-time → Assistant&lt;/li&gt;
&lt;li&gt;Ongoing → Agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Am I trying to learn something or automate something?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn → Assistant&lt;/li&gt;
&lt;li&gt;Automate → Agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Do I need this to work when I'm not around?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No → Assistant&lt;/li&gt;
&lt;li&gt;Yes → Agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simple as that.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Means for Different People
&lt;/h2&gt;

&lt;h3&gt;
  
  
  If You're a Developer:
&lt;/h3&gt;

&lt;p&gt;Learn both. Understanding how to build assistants and agents is becoming an important skill. Start with assistants (easier), then explore agents (more complex). Focus on safety, monitoring, and good design patterns.&lt;/p&gt;

&lt;p&gt;Developers who understand agentic AI will have an advantage as this technology matures.&lt;/p&gt;

&lt;h3&gt;
  
  
  If You're Running a Business:
&lt;/h3&gt;

&lt;p&gt;Look at your workflows. Where are people doing repetitive, multi-step tasks? Those are agent candidates. Where do people need information and advice? Those are assistant use cases.&lt;/p&gt;

&lt;p&gt;Start with one agent for one workflow. Measure the impact. If it works, expand. Don't try to automate everything at once.&lt;/p&gt;

&lt;p&gt;And remember: the goal isn't to replace people. It's to free them up to do more valuable work.&lt;/p&gt;

&lt;h3&gt;
  
  
  If You're Just Curious:
&lt;/h3&gt;

&lt;p&gt;Try ChatGPT or Claude if you haven't already. That's an assistant. Play with it. See what it can and can't do.&lt;/p&gt;

&lt;p&gt;Then watch for agent capabilities showing up in tools you use. GitHub Copilot, AWS services, automation platforms - agents are being built into everything.&lt;/p&gt;

&lt;p&gt;Understanding this difference will help you make sense of where AI is actually going.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The AI revolution isn't just about smarter answers. It's about AI that can actually do things.&lt;/p&gt;

&lt;p&gt;For years, we've had AI that could think but not act. Now we have AI that can do both. That's a fundamental shift, and most people haven't caught up to it yet.&lt;/p&gt;

&lt;p&gt;AI assistants made us more informed. They gave us access to knowledge and helped us think through problems. That's valuable, and it's not going away.&lt;/p&gt;

&lt;p&gt;Agentic AI is making us more productive. It's taking tasks off our plate and handling them autonomously. That's powerful, and it's just getting started.&lt;/p&gt;

&lt;p&gt;The key is understanding which tool solves which problem. Don't use an assistant when you need an agent. Don't use an agent when you just need advice.&lt;/p&gt;

&lt;p&gt;We're at the beginning of the agentic AI era. The assistants aren't going away - they're just getting company. And together, they're changing how we work.&lt;/p&gt;

&lt;p&gt;The question isn't whether you should use AI. The question is: which AI should you use, and for what?&lt;/p&gt;

&lt;p&gt;Now you know the answer.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading! I hope this article gave you practical insights and a clearer perspective on the topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Was this helpful?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today&lt;/li&gt;
&lt;li&gt;💾 Save for your next optimization session&lt;/li&gt;
&lt;li&gt;🔄 Share with your team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Follow me for more on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS architecture patterns&lt;/li&gt;
&lt;li&gt;FinOps automation&lt;/li&gt;
&lt;li&gt;Multi-account strategies&lt;/li&gt;
&lt;li&gt;AI-driven DevOps&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives coming soon on cloud operations, GenAI, Agentic-AI, DevOps, and data workflows follow for weekly insights.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts drop a comment or connect with me on &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, feel free to reach out directly at &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Learning&lt;/strong&gt; 🚀&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>discuss</category>
      <category>agents</category>
    </item>
    <item>
      <title>Terraform State: The One File You Can't Afford to Lose</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Sat, 21 Mar 2026 19:03:47 +0000</pubDate>
      <link>https://forem.com/aws-builders/terraform-state-the-one-file-you-cant-afford-to-lose-33l4</link>
      <guid>https://forem.com/aws-builders/terraform-state-the-one-file-you-cant-afford-to-lose-33l4</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"State is not just a file it's the single source of truth for your entire infrastructure."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🎯 Welcome Back!
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://dev.to/aws-builders/your-first-infrastructure-as-code-in-four-commands-46ep"&gt;Article 3&lt;/a&gt;, you created your first S3 bucket and noticed a mysterious file appear: &lt;code&gt;terraform.tfstate&lt;/code&gt;. I briefly mentioned it was "Terraform's memory," but we didn't dive deep.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today, that changes.&lt;/strong&gt; Understanding state is what separates beginners from confident Terraform users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the end of this article, you'll:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Understand what state is and why it's critical&lt;/li&gt;
&lt;li&gt;✅ Use state commands to inspect and manage infrastructure&lt;/li&gt;
&lt;li&gt;✅ Import existing AWS resources into Terraform&lt;/li&gt;
&lt;li&gt;✅ Handle state drift and conflicts&lt;/li&gt;
&lt;li&gt;✅ Know when things go wrong and how to fix them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time Required:&lt;/strong&gt; 25 minutes&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; $0 (using free tier resources)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Difficulty:&lt;/strong&gt; Intermediate&lt;/p&gt;

&lt;p&gt;Let's unlock Terraform's most important concept! 🔓&lt;/p&gt;


&lt;h2&gt;
  
  
  🤔 The Problem: Why Does State Even Exist?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  A Quick Thought Experiment
&lt;/h3&gt;

&lt;p&gt;Imagine you run &lt;code&gt;terraform apply&lt;/code&gt; and create an S3 bucket. Then you close your terminal and come back tomorrow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; How does Terraform know that bucket exists?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your &lt;code&gt;.tf&lt;/code&gt; files?&lt;/strong&gt; No they only describe what &lt;em&gt;should&lt;/em&gt; exist, not what &lt;em&gt;actually&lt;/em&gt; exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS API?&lt;/strong&gt; Terraform could query AWS every time, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;That's slow (imagine 100+ resources)&lt;/li&gt;
&lt;li&gt;AWS doesn't know which resources Terraform created&lt;/li&gt;
&lt;li&gt;No way to track metadata or dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Answer:&lt;/strong&gt; The state file.&lt;/p&gt;


&lt;h2&gt;
  
  
  📋 What is Terraform State?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Simple Definition
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;State is a JSON file that maps your Terraform configuration to real-world resources.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your &lt;code&gt;.tf&lt;/code&gt; files&lt;/strong&gt; = The blueprint (what you want)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State file&lt;/strong&gt; = The inventory (what actually exists)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS&lt;/strong&gt; = The actual building&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  What State Stores
&lt;/h3&gt;

&lt;p&gt;Let's look at a real state file from our S3 bucket:&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;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"terraform_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.14.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"resources"&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"managed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my_first_bucket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"provider[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;registry.terraform.io/hashicorp/aws&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"instances"&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"attributes"&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;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"terraform-first-bucket-yourname-2026"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"arn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::terraform-first-bucket-yourname-2026"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"bucket"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"terraform-first-bucket-yourname-2026"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"region"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"tags"&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;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My First Terraform Bucket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"Environment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learning"&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;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;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;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;p&gt;&lt;strong&gt;State tracks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Resource type (&lt;code&gt;aws_s3_bucket&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;✅ Resource name in your code (&lt;code&gt;my_first_bucket&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;✅ Actual AWS resource ID&lt;/li&gt;
&lt;li&gt;✅ All attributes (ARN, region, tags, etc.)&lt;/li&gt;
&lt;li&gt;✅ Dependencies between resources&lt;/li&gt;
&lt;li&gt;✅ Provider information&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔄 How Terraform Uses State
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Terraform Workflow (Revisited)
&lt;/h3&gt;

&lt;p&gt;When you run &lt;code&gt;terraform plan&lt;/code&gt; or &lt;code&gt;terraform apply&lt;/code&gt;, here's what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Read your .tf files (desired state)
   ↓
2. Read terraform.tfstate (current state)
   ↓
3. Query AWS to verify current state
   ↓
4. Calculate the difference (the "plan")
   ↓
5. Show you what will change
   ↓
6. Apply changes (if you approve)
   ↓
7. Update state file with new information
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Without state, Terraform would:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Try to create resources that already exist&lt;/li&gt;
&lt;li&gt;❌ Not know what to update or delete&lt;/li&gt;
&lt;li&gt;❌ Lose track of dependencies&lt;/li&gt;
&lt;li&gt;❌ Be unable to manage infrastructure&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Hands-On: State Commands
&lt;/h2&gt;

&lt;p&gt;Let's create some infrastructure and explore state commands.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create Test Infrastructure
&lt;/h3&gt;

&lt;p&gt;Create a new 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;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/terraform-state-demo
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/terraform-state-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;main.tf&lt;/code&gt;:&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.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; 5.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="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Create two S3 buckets&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"logs"&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-app-logs-yourname-2026"&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"Application Logs"&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;"Development"&lt;/span&gt;
    &lt;span class="nx"&gt;Purpose&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Logging"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"backups"&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-app-backups-yourname-2026"&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"Application Backups"&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;"Development"&lt;/span&gt;
    &lt;span class="nx"&gt;Purpose&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Backup Storage"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Outputs&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"logs_bucket_id"&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;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;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"backups_bucket_id"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backups&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;/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.amazonaws.com%2Fuploads%2Farticles%2Fhw1kiluy74y49yy2b45n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhw1kiluy74y49yy2b45n.png" alt=" " width="784" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Remember:&lt;/strong&gt; Change &lt;code&gt;yourname&lt;/code&gt; to something unique!&lt;/p&gt;

&lt;p&gt;Apply the 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 init
terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type &lt;code&gt;yes&lt;/code&gt; when prompted.&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%2F25oelkf26koq9ezcw7e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25oelkf26koq9ezcw7e2.png" alt=" " width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Command 1: terraform state list
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; See all resources Terraform is managing.&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;&lt;strong&gt;Output:&lt;/strong&gt;&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;aws_s3_bucket&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backups&lt;/span&gt;
&lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logs&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.amazonaws.com%2Fuploads%2Farticles%2F87b3brcqu133w4ijeppu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F87b3brcqu133w4ijeppu.png" alt=" " width="800" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Quickly see what's in your state without opening the JSON file.&lt;/p&gt;




&lt;h3&gt;
  
  
  Command 2: terraform state show
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; Get detailed information about a specific resource.&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.logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&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="c1"&gt;# aws_s3_bucket.logs:&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"logs"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;arn&lt;/span&gt;                         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:s3:::my-app-logs-yourname-2026"&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-app-logs-yourname-2026"&lt;/span&gt;
    &lt;span class="nx"&gt;bucket_domain_name&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-app-logs-yourname-2026.s3.amazonaws.com"&lt;/span&gt;
    &lt;span class="nx"&gt;hosted_zone_id&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Z3AQBSTGFYJSTF"&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-app-logs-yourname-2026"&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;tags&lt;/span&gt;                        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Development"&lt;/span&gt;
        &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Application Logs"&lt;/span&gt;
        &lt;span class="s2"&gt;"Purpose"&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Logging"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;# ... more attributes&lt;/span&gt;
&lt;span class="p"&gt;}&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.amazonaws.com%2Fuploads%2Farticles%2Fyr2h7s23o2tfvebj9cvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyr2h7s23o2tfvebj9cvg.png" alt=" " width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Debug issues, verify configurations, check resource attributes.&lt;/p&gt;




&lt;h3&gt;
  
  
  Command 3: terraform show
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; Display the entire state in human-readable format.&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;&lt;strong&gt;Output:&lt;/strong&gt; Shows all resources with their complete configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Get a complete overview of your infrastructure.&lt;/p&gt;




&lt;h3&gt;
  
  
  Command 4: terraform state pull
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; Download and display the raw 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 pull
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt; Raw JSON state file content.&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%2Ffo3mtd32wrhryp4or3rd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo3mtd32wrhryp4or3rd.png" alt=" " width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Backup state, inspect state structure, debugging.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 Real-World Scenario: Importing Existing Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;You have an S3 bucket created manually in AWS Console (before you knew Terraform). Now you want Terraform to manage it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can't just write the Terraform code and run &lt;code&gt;apply&lt;/code&gt;&lt;/strong&gt; Terraform will try to create a new bucket and fail (bucket names are unique).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Import the existing resource into Terraform state.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step-by-Step: Import an Existing Bucket
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create a bucket manually in AWS Console&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://s3.console.aws.amazon.com/s3/buckets" rel="noopener noreferrer"&gt;S3 Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click "Create bucket"&lt;/li&gt;
&lt;li&gt;Name it: &lt;code&gt;manual-bucket-yourname-2026&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Keep all defaults&lt;/li&gt;
&lt;li&gt;Click "Create bucket"&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;&lt;strong&gt;Step 2: Write Terraform code for it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add to your &lt;code&gt;main.tf&lt;/code&gt;:&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_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"manual"&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;"manual-bucket-yourname-2026"&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"Manually Created Bucket"&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;"Development"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&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="p"&gt;}&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.amazonaws.com%2Fuploads%2Farticles%2Ft5iktzwdfn1xkvvmdfgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft5iktzwdfn1xkvvmdfgv.png" alt=" " width="633" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Try to apply (this will fail)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You'll see:&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;Error: creating S3 Bucket (manual-bucket-yourname-2026): 
BucketAlreadyOwnedByYou: Your previous request to create the named bucket succeeded
&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.amazonaws.com%2Fuploads%2Farticles%2Fc3atgb2sldhxaacdsmwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3atgb2sldhxaacdsmwg.png" alt=" " width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terraform doesn't know the bucket exists!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Step 4: Import the bucket into state&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform import aws_s3_bucket.manual manual-bucket-yourname-2026
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform import &amp;lt;resource_type&amp;gt;.&amp;lt;resource_name&amp;gt; &amp;lt;aws_resource_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&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;aws_s3_bucket.manual: Importing from ID "manual-bucket-yourname-2026"...
aws_s3_bucket.manual: Import prepared!
aws_s3_bucket.manual: Refreshing state...

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

&lt;p&gt;&lt;strong&gt;Step 5: Verify the import&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&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;aws_s3_bucket&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backups&lt;/span&gt;
&lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logs&lt;/span&gt;
&lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;manual&lt;/span&gt;    &lt;span class="err"&gt;←&lt;/span&gt; &lt;span class="nx"&gt;New&lt;/span&gt;&lt;span class="err"&gt;!&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.amazonaws.com%2Fuploads%2Farticles%2Fbo2shpzdeztyb8m0tjam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbo2shpzdeztyb8m0tjam.png" alt=" " width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Run plan to sync tags&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You'll see:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# aws_s3_bucket.manual will be updated in-place&lt;/span&gt;
  &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"manual"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Development"&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"ManagedBy"&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Manually Created Bucket"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;p&gt;Terraform will add the tags we defined!&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;&lt;strong&gt;Now Terraform fully manages this bucket!&lt;/strong&gt; 🎉&lt;/p&gt;

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




&lt;h2&gt;
  
  
  🚨 Understanding State Drift
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is State Drift?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;State drift&lt;/strong&gt; happens when the real infrastructure doesn't match what's in the state file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common causes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Someone manually changes resources in AWS Console&lt;/li&gt;
&lt;li&gt;Another tool modifies resources&lt;/li&gt;
&lt;li&gt;AWS makes automatic changes&lt;/li&gt;
&lt;li&gt;State file gets corrupted&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Detecting Drift
&lt;/h3&gt;

&lt;p&gt;Let's simulate drift:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Manually change a bucket in AWS Console&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to S3 Console&lt;/li&gt;
&lt;li&gt;Open your &lt;code&gt;my-app-logs-yourname-2026&lt;/code&gt; bucket&lt;/li&gt;
&lt;li&gt;Go to "Properties" → "Tags"&lt;/li&gt;
&lt;li&gt;Add a new tag: &lt;code&gt;ManualChange = Yes&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;&lt;strong&gt;Step 2: Run terraform plan&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# aws_s3_bucket.logs will be updated in-place&lt;/span&gt;
  &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"logs"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"ManualChange"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Yes"&lt;/span&gt; &lt;span class="nx"&gt;-&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
            &lt;span class="c1"&gt;# (3 unchanged elements hidden)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;strong&gt;Terraform detected the drift!&lt;/strong&gt; It will remove the manual tag to match your code.&lt;/p&gt;




&lt;h3&gt;
  
  
  Refreshing State
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; Update state file to match real infrastructure without making changes.&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;&lt;strong&gt;Or (recommended in newer versions):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This updates state to match reality without modifying resources.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; After manual changes, sync state before planning changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Advanced State Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Moving Resources in State
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; You want to rename a resource in your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; If you just rename it, Terraform will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Destroy the old resource&lt;/li&gt;
&lt;li&gt;Create a new resource&lt;/li&gt;
&lt;li&gt;You lose data!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use &lt;code&gt;terraform state mv&lt;/code&gt;&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Rename logs bucket to app_logs in code&lt;/span&gt;
terraform state &lt;span class="nb"&gt;mv &lt;/span&gt;aws_s3_bucket.logs aws_s3_bucket.app_logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now update your &lt;code&gt;main.tf&lt;/code&gt; to match:&lt;/strong&gt;&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_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"app_logs"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;# Changed from "logs"&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-app-logs-yourname-2026"&lt;/span&gt;
  &lt;span class="c1"&gt;# ... rest of config&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Also update the output reference&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"logs_bucket_id"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app_logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;  &lt;span class="c1"&gt;# Changed from .logs to .app_logs&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;⚠️ Important:&lt;/strong&gt; After renaming with &lt;code&gt;state mv&lt;/code&gt;, update ALL references including outputs, data sources, and dependencies in other resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run plan:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&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;No changes. Your infrastructure matches the configuration.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Perfect!&lt;/strong&gt; No resources destroyed.&lt;/p&gt;




&lt;h3&gt;
  
  
  Removing Resources from State
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; You want Terraform to stop managing a resource (but keep it in AWS).&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.manual
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&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;Removed aws_s3_bucket.manual
Successfully removed 1 resource instance(s).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Resource still exists in AWS&lt;/li&gt;
&lt;li&gt;Terraform no longer tracks it&lt;/li&gt;
&lt;li&gt;You can manage it manually or with another tool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Migrating resources to another Terraform project, or handing off to another team.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 State Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Never Edit State Files Manually
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;❌ Don't do this:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano terraform.tfstate  &lt;span class="c"&gt;# NEVER!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;✅ Use state commands instead:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; Manual edits can corrupt state and break your infrastructure.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Always Backup State Before Major Changes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Backup state&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;terraform.tfstate terraform.tfstate.backup

&lt;span class="c"&gt;# Or use state pull&lt;/span&gt;
terraform state pull &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; state-backup-&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%Y%m%d&lt;span class="si"&gt;)&lt;/span&gt;.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Use Version Control (But Not for State!)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Add to &lt;code&gt;.gitignore&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .gitignore &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
# Terraform files
.terraform/
*.tfstate
*.tfstate.backup
.terraform.lock.hcl

# Variable files with secrets
*.tfvars
*.auto.tfvars
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why not commit state?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contains sensitive data (passwords, keys)&lt;/li&gt;
&lt;li&gt;Can cause merge conflicts&lt;/li&gt;
&lt;li&gt;Not designed for version control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What to commit:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;code&gt;.tf&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;.gitignore&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;README.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ Documentation&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Use Remote State for Teams
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Local state doesn't work for teams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Remote state (we'll cover in Article 8).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preview:&lt;/strong&gt;&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"&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;"prod/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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🐛 Common State Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: State File Locked
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&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;Error: Error acquiring the state lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cause:&lt;/strong&gt; Another &lt;code&gt;terraform apply&lt;/code&gt; is running, or previous run crashed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Wait for other operation to finish, or&lt;/span&gt;
terraform force-unlock &amp;lt;lock-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;⚠️ Only force-unlock if you're sure no other process is running!&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Issue 2: State Out of Sync
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&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;Error: Resource already exists
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Refresh state&lt;/span&gt;
terraform apply &lt;span class="nt"&gt;-refresh-only&lt;/span&gt;

&lt;span class="c"&gt;# Or import the resource&lt;/span&gt;
terraform import &amp;lt;resource_type&amp;gt;.&amp;lt;name&amp;gt; &amp;lt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Issue 3: Lost State File
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Accidentally deleted &lt;code&gt;terraform.tfstate&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Option 1:&lt;/strong&gt; Restore from backup&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;cp &lt;/span&gt;terraform.tfstate.backup terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option 2:&lt;/strong&gt; Rebuild state by importing all 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 import aws_s3_bucket.logs my-app-logs-yourname-2026
terraform import aws_s3_bucket.backups my-app-backups-yourname-2026
&lt;span class="c"&gt;# ... import all resources&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option 3:&lt;/strong&gt; If using remote state, re-initialize&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;h3&gt;
  
  
  Issue 4: Corrupted State
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptoms:&lt;/strong&gt; Strange errors, resources not found, plan shows unexpected changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Restore from backup&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;terraform.tfstate.backup terraform.tfstate

&lt;span class="c"&gt;# Or pull from remote state&lt;/span&gt;
terraform state pull &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Hands-On Challenge
&lt;/h2&gt;

&lt;p&gt;Before moving to the next article, complete these challenges:&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 1: State Inspection
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;List all resources in your state&lt;/li&gt;
&lt;li&gt;Show detailed info for the backups bucket&lt;/li&gt;
&lt;li&gt;Pull the raw state and save it to a file&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Challenge 2: Import Practice
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a new S3 bucket manually in AWS Console&lt;/li&gt;
&lt;li&gt;Write Terraform code for it&lt;/li&gt;
&lt;li&gt;Import it into your state&lt;/li&gt;
&lt;li&gt;Verify with &lt;code&gt;terraform plan&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Challenge 3: Drift Detection
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Manually add a tag to one of your buckets in AWS Console&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;terraform plan&lt;/code&gt; to detect the drift&lt;/li&gt;
&lt;li&gt;Decide: keep the manual change or revert it&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Challenge 4: State Manipulation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Rename one of your resources in code&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;terraform state mv&lt;/code&gt; to update state&lt;/li&gt;
&lt;li&gt;Verify no resources will be destroyed&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Challenge 5: Cleanup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Remove one resource from state (but keep in AWS)&lt;/li&gt;
&lt;li&gt;Verify it's no longer tracked&lt;/li&gt;
&lt;li&gt;Manually delete it from AWS Console&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🧹 Cleanup
&lt;/h2&gt;

&lt;p&gt;Let's clean up the resources we created:&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; ~/terraform-state-demo

&lt;span class="c"&gt;# Destroy all resources&lt;/span&gt;
terraform destroy

&lt;span class="c"&gt;# Verify in AWS Console&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;ls&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;yourname

&lt;span class="c"&gt;# Remove directory&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; terraform-state-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📊 State File Structure Explained
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Key Sections
&lt;/h3&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;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;State&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;version&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"terraform_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.14.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Terraform&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;used&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"serial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Increments&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;each&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;change&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lineage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"abc-123-def"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Unique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;state&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outputs"&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;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;values&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"resources"&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;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;All&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;managed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;resources&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;p&gt;&lt;strong&gt;Important fields:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;version:&lt;/strong&gt; State format version (currently 4)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;serial:&lt;/strong&gt; Increments with each state change (helps detect conflicts)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lineage:&lt;/strong&gt; Unique identifier for this state file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;resources:&lt;/strong&gt; Array of all managed resources&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎓 What You Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;State Fundamentals:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ State maps Terraform code to real resources&lt;/li&gt;
&lt;li&gt;✅ State is the single source of truth&lt;/li&gt;
&lt;li&gt;✅ State enables Terraform to calculate changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;State Commands:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;code&gt;terraform state list&lt;/code&gt; - List all resources&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;terraform state show&lt;/code&gt; - Show resource details&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;terraform state mv&lt;/code&gt; - Rename resources&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;terraform state rm&lt;/code&gt; - Remove from state&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;terraform import&lt;/code&gt; - Import existing resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;State Management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Detect and handle state drift&lt;/li&gt;
&lt;li&gt;✅ Import existing infrastructure&lt;/li&gt;
&lt;li&gt;✅ Backup and restore state&lt;/li&gt;
&lt;li&gt;✅ Troubleshoot common issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Never edit state manually&lt;/li&gt;
&lt;li&gt;✅ Always backup before major changes&lt;/li&gt;
&lt;li&gt;✅ Never commit state to Git&lt;/li&gt;
&lt;li&gt;✅ Use remote state for teams&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎬 What's Next?
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;Article 5: Variables and Outputs - Making Code Reusable&lt;/strong&gt;, you'll learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to parameterize your Terraform code&lt;/li&gt;
&lt;li&gt;Using input variables for flexibility&lt;/li&gt;
&lt;li&gt;Creating reusable configurations&lt;/li&gt;
&lt;li&gt;Managing different environments (dev/staging/prod)&lt;/li&gt;
&lt;li&gt;Working with variable files&lt;/li&gt;
&lt;li&gt;Sensitive data handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You'll build:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A reusable S3 bucket module&lt;/li&gt;
&lt;li&gt;Environment-specific configurations&lt;/li&gt;
&lt;li&gt;Dynamic resource naming&lt;/li&gt;
&lt;li&gt;Secure variable management&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📚 Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform State Documentation:&lt;/strong&gt; &lt;a href="https://developer.hashicorp.com/terraform/language/state" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/language/state&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Commands:&lt;/strong&gt; &lt;a href="https://developer.hashicorp.com/terraform/cli/commands/state" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/cli/commands/state&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import Command:&lt;/strong&gt; &lt;a href="https://developer.hashicorp.com/terraform/cli/import" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/cli/import&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading. I hope this article provided practical insights and a clearer understanding of the topic.&lt;/p&gt;

&lt;p&gt;If you found this useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value
&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today
&lt;/li&gt;
&lt;li&gt;💾 Save it for your next optimization session
&lt;/li&gt;
&lt;li&gt;🔄 Share it with your team
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives are coming soon on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Operations&lt;/li&gt;
&lt;li&gt;GenAI &amp;amp; Agentic AI&lt;/li&gt;
&lt;li&gt;DevOps Automation&lt;/li&gt;
&lt;li&gt;Data &amp;amp; Platform Engineering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow along for weekly insights and hands-on guides.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts. Feel free to drop a comment or connect with me on:&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, reach out at:&lt;/p&gt;

&lt;p&gt;📧 &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Found this helpful? Share it with your team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⭐ Star the repo • 📖 Follow the series • 💬 Ask questions  &lt;/p&gt;

&lt;p&gt;Made by &lt;strong&gt;Sarvar Nadaf&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🌐 &lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;https://sarvarnadaf.com&lt;/a&gt;&lt;/p&gt;




</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Your First Infrastructure as Code in Four Commands</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Mon, 16 Mar 2026 23:31:39 +0000</pubDate>
      <link>https://forem.com/aws-builders/your-first-infrastructure-as-code-in-four-commands-46ep</link>
      <guid>https://forem.com/aws-builders/your-first-infrastructure-as-code-in-four-commands-46ep</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The journey from clicking to coding starts with a single resource."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🎯 Welcome Back!
&lt;/h2&gt;

&lt;p&gt;Remember in &lt;a href="https://dev.to/aws-builders/why-every-developer-should-learn-terraform-in-2026-and-how-to-start--4fk0"&gt;Article 1&lt;/a&gt; when I showed you the pain of clicking through AWS Console for hours? And in &lt;a href="https://dev.to/aws-builders/installing-terraform-and-setting-up-your-environment-1j9b"&gt;Article 2&lt;/a&gt; we got Terraform installed?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today, you'll experience the magic moment&lt;/strong&gt; - creating real AWS infrastructure with just a few lines of code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the end of this article, you'll:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Understand the Terraform workflow (the 4 commands you'll use forever)&lt;/li&gt;
&lt;li&gt;✅ Write your first &lt;code&gt;.tf&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;✅ Create an actual S3 bucket on AWS&lt;/li&gt;
&lt;li&gt;✅ Understand what a state file is and why it matters&lt;/li&gt;
&lt;li&gt;✅ Clean up resources properly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time Required:&lt;/strong&gt; 20 minutes&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; $0 (S3 bucket is free tier)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Difficulty:&lt;/strong&gt; Beginner-friendly&lt;/p&gt;

&lt;p&gt;Let's create some infrastructure! 🚀&lt;/p&gt;


&lt;h2&gt;
  
  
  💡 Quick Theory: The Terraform Workflow
&lt;/h2&gt;

&lt;p&gt;Before we dive in, you need to know the &lt;strong&gt;4 commands&lt;/strong&gt; that form the core Terraform workflow. You'll use these commands for every project, whether you're creating a simple S3 bucket or a complex multi-tier application.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Magic 4 Commands:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init      &lt;span class="c"&gt;# Initialize - Download providers&lt;/span&gt;
terraform plan      &lt;span class="c"&gt;# Preview - See what will change&lt;/span&gt;
terraform apply     &lt;span class="c"&gt;# Execute - Create the resources&lt;/span&gt;
terraform destroy   &lt;span class="c"&gt;# Cleanup - Remove everything&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Think of it like cooking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;init&lt;/strong&gt; = Get your ingredients and tools ready&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;plan&lt;/strong&gt; = Read the recipe and imagine the final dish&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;apply&lt;/strong&gt; = Actually cook the meal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;destroy&lt;/strong&gt; = Clean up the kitchen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;That's it!&lt;/strong&gt; Master these 4 commands, and you've mastered the Terraform workflow.&lt;/p&gt;


&lt;h2&gt;
  
  
  📝 Understanding Terraform Files
&lt;/h2&gt;

&lt;p&gt;Terraform uses files with &lt;code&gt;.tf&lt;/code&gt; extension written in &lt;strong&gt;HCL&lt;/strong&gt; (HashiCorp Configuration Language). Don't worry - it's much simpler than it sounds!&lt;/p&gt;
&lt;h3&gt;
  
  
  Basic Structure:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This is a comment&lt;/span&gt;

&lt;span class="nx"&gt;block_type&lt;/span&gt; &lt;span class="s2"&gt;"label"&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;argument&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"value"&lt;/span&gt;
  &lt;span class="nx"&gt;another_argument&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Three main block types you'll use:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;terraform&lt;/strong&gt; - Configuration settings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;provider&lt;/strong&gt; - Which cloud (AWS, Azure, GCP)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;resource&lt;/strong&gt; - What to create (S3, EC2, etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's see them in action!&lt;/p&gt;


&lt;h2&gt;
  
  
  🛠️ Hands-On: Create Your First S3 Bucket
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1: Create Your Project Directory
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a directory for your first Terraform project&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/terraform-first-resource
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/terraform-first-resource
&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.amazonaws.com%2Fuploads%2Farticles%2Fdg1uwurp02bdo8hd8gjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdg1uwurp02bdo8hd8gjy.png" alt=" " width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Write Your First Terraform Code
&lt;/h3&gt;

&lt;p&gt;Create a file called &lt;code&gt;main.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano main.tf
&lt;span class="c"&gt;# Or use your favorite editor: vim, VS Code, etc.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Copy this code:&lt;/strong&gt;&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="c1"&gt;# Terraform configuration block&lt;/span&gt;
&lt;span class="c1"&gt;# Specifies Terraform version and required providers&lt;/span&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.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; 5.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="c1"&gt;# Provider configuration&lt;/span&gt;
&lt;span class="c1"&gt;# Tells Terraform to use AWS in us-east-1 region&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="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Resource block - This creates the actual S3 bucket&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"my_first_bucket"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;# Bucket name must be globally unique across ALL AWS accounts&lt;/span&gt;
  &lt;span class="c1"&gt;# Replace 'yourname' with your actual name or username&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;"terraform-first-bucket-yourname-2026"&lt;/span&gt;

  &lt;span class="c1"&gt;# Tags help organize and track resources&lt;/span&gt;
  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"My First Terraform Bucket"&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;"Learning"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&lt;/span&gt;
    &lt;span class="nx"&gt;CreatedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"YourName"&lt;/span&gt;
    &lt;span class="nx"&gt;Updated&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Yes"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Output block - Displays information after creation&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_name"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;my_first_bucket&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;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The name of the S3 bucket"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_arn"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;my_first_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&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;"The ARN of the S3 bucket"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"bucket_region"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;my_first_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&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;"The region where bucket is created"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;⚠️ Important:&lt;/strong&gt; Change &lt;code&gt;yourname&lt;/code&gt; in the bucket name to something unique (your name, username, or random string). S3 bucket names must be globally unique across ALL AWS accounts!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Save the file&lt;/strong&gt; (Ctrl+X, then Y, then Enter if using nano)&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%2Fyapg8d2eh7gw9992p243.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyapg8d2eh7gw9992p243.png" alt=" " width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 The 4 Commands in Action
&lt;/h2&gt;

&lt;p&gt;Now comes the exciting part! Let's run our 4 magic commands.&lt;/p&gt;

&lt;h3&gt;
  
  
  Command 1: terraform init
&lt;/h3&gt;

&lt;p&gt;This downloads the AWS provider plugin.&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;&lt;strong&gt;You'll see:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Initializing the backend...
Initializing provider plugins...
&lt;/span&gt;&lt;span class="gp"&gt;- Finding hashicorp/aws versions matching "~&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;5.0&lt;span class="s2"&gt;"...
&lt;/span&gt;&lt;span class="go"&gt;- Installing hashicorp/aws v5.x.x...
- Installed hashicorp/aws v5.x.x

Terraform has been successfully initialized!
&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.amazonaws.com%2Fuploads%2Farticles%2Fgm7maja04shq16gwci41.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgm7maja04shq16gwci41.png" alt=" " width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What just happened?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform downloaded the AWS provider plugin&lt;/li&gt;
&lt;li&gt;Created a &lt;code&gt;.terraform/&lt;/code&gt; directory (hidden folder)&lt;/li&gt;
&lt;li&gt;Created &lt;code&gt;.terraform.lock.hcl&lt;/code&gt; file (locks provider versions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; You only need to run &lt;code&gt;init&lt;/code&gt; once per project, or when you add new providers.&lt;/p&gt;




&lt;h3&gt;
  
  
  Command 2: terraform plan
&lt;/h3&gt;

&lt;p&gt;This shows you what Terraform will create (without actually creating it).&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;&lt;strong&gt;You'll see:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="nx"&gt;Terraform&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;perform&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;

  &lt;span class="c1"&gt;# aws_s3_bucket.my_first_bucket will be created&lt;/span&gt;
  &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"my_first_bucket"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="err"&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;"terraform-first-bucket-yourname-2026"&lt;/span&gt;
      &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;bucket_domain_name&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;known&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;                          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;known&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;region&lt;/span&gt;                      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;known&lt;/span&gt; &lt;span class="nx"&gt;after&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;                        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"CreatedBy"&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"YourName"&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"Environment"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Learning"&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"ManagedBy"&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"Name"&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"My First Terraform Bucket"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Plan&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="err"&gt;.&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.amazonaws.com%2Fuploads%2Farticles%2Fnnx4vd4ws2uycpfdh3wd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnnx4vd4ws2uycpfdh3wd.png" alt=" " width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding the output:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;+&lt;/code&gt; means "will be created"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~&lt;/code&gt; means "will be modified" (you'll see this later)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-&lt;/code&gt; means "will be destroyed"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(known after apply)&lt;/code&gt; means AWS will generate this value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This is your safety check!&lt;/strong&gt; Always review the plan before applying.&lt;/p&gt;




&lt;h3&gt;
  
  
  Command 3: terraform apply
&lt;/h3&gt;

&lt;p&gt;This actually creates the resources on AWS.&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;&lt;strong&gt;Terraform will show the plan again and ask for confirmation:&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;Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

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

&lt;p&gt;&lt;strong&gt;Type &lt;code&gt;yes&lt;/code&gt; and press Enter.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You'll see:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;aws_s3_bucket.my_first_bucket: Creating...
aws_s3_bucket.my_first_bucket: Creation complete after 2s [id=terraform-first-bucket-yourname-2026]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

bucket_arn = "arn:aws:s3:::terraform-first-bucket-yourname-2026"
bucket_name = "terraform-first-bucket-yourname-2026"
bucket_region = "us-east-1"
&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.amazonaws.com%2Fuploads%2Farticles%2F2na5e9ihjij39nn4xora.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2na5e9ihjij39nn4xora.png" alt=" " width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎉 Congratulations!&lt;/strong&gt; You just created your first AWS resource with code!&lt;/p&gt;




&lt;h3&gt;
  
  
  Verify in AWS Console
&lt;/h3&gt;

&lt;p&gt;Let's confirm it's really there:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://s3.console.aws.amazon.com/s3/buckets" rel="noopener noreferrer"&gt;AWS S3 Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You should see your bucket: &lt;code&gt;terraform-first-bucket-yourname-2026&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click on it and check the &lt;strong&gt;Tags&lt;/strong&gt; tab - you'll see all the tags you defined!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;This is the "aha!" moment&lt;/strong&gt; - you created AWS infrastructure without clicking through the console!&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%2Fhoyvlyefrwk8hm1bm02j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoyvlyefrwk8hm1bm02j.png" alt=" " width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

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




&lt;h2&gt;
  
  
  🗂️ Understanding the State File
&lt;/h2&gt;

&lt;p&gt;After running &lt;code&gt;terraform apply&lt;/code&gt;, you'll notice a new file: &lt;code&gt;terraform.tfstate&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You'll see:&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/
.terraform.lock.hcl
main.tf
terraform.tfstate
&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.amazonaws.com%2Fuploads%2Farticles%2Fathbwlbjnwsi2ixx6ovb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fathbwlbjnwsi2ixx6ovb.png" alt=" " width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the State File?
&lt;/h3&gt;

&lt;p&gt;The state file is &lt;strong&gt;Terraform's memory&lt;/strong&gt;. It stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What resources Terraform created&lt;/li&gt;
&lt;li&gt;Current configuration of those resources&lt;/li&gt;
&lt;li&gt;Metadata and dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Let's peek inside:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see JSON with details about your S3 bucket - its name, ARN, region, tags, etc.&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%2Fggiudxq8gpp0i7godptv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggiudxq8gpp0i7godptv.png" alt=" " width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Does State Matter?
&lt;/h3&gt;

&lt;p&gt;When you run &lt;code&gt;terraform plan&lt;/code&gt; or &lt;code&gt;terraform apply&lt;/code&gt; again, Terraform:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reads the state file to know what exists&lt;/li&gt;
&lt;li&gt;Compares it with your &lt;code&gt;.tf&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;Calculates what needs to change&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Without state, Terraform wouldn't know what it created!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Important State Rules:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Never edit state files manually&lt;/li&gt;
&lt;li&gt;Never delete state files (you'll lose track of resources)&lt;/li&gt;
&lt;li&gt;Never commit state files to Git (they contain sensitive data)&lt;/li&gt;
&lt;li&gt;For teams, use remote state (we'll cover this in Article 8)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Let's Make a Change
&lt;/h2&gt;

&lt;p&gt;Now let's see Terraform's power - making changes to existing infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edit your &lt;code&gt;main.tf&lt;/code&gt; file and add a new tag:&lt;/strong&gt;&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_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"my_first_bucket"&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;"terraform-first-bucket-yourname-2026"&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&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;"My First Terraform Bucket"&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;"Learning"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&lt;/span&gt;
    &lt;span class="nx"&gt;CreatedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"YourName"&lt;/span&gt;
    &lt;span class="nx"&gt;Updated&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Yes"&lt;/span&gt;  
    &lt;span class="nx"&gt;LastUpdated&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Today"&lt;/span&gt;  &lt;span class="c1"&gt;# ← Add this new tag&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run plan again:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You'll see:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# aws_s3_bucket.my_first_bucket will be updated in-place&lt;/span&gt;
  &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"my_first_bucket"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"Updated"&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Yes"&lt;/span&gt;
            &lt;span class="c1"&gt;# (5 unchanged elements hidden)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Plan&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="err"&gt;.&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.amazonaws.com%2Fuploads%2Farticles%2Ffi043unc9xz0ilzzcjzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffi043unc9xz0ilzzcjzc.png" alt=" " width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the &lt;code&gt;~&lt;/code&gt; symbol - it means "modify existing resource"!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apply the change:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Type &lt;code&gt;yes&lt;/code&gt; when prompted.&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%2Fpdoe5ulhmrqr082escdb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdoe5ulhmrqr082escdb.png" alt=" " width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check AWS Console&lt;/strong&gt; - your bucket now has the new tag!&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%2Fi4wu7iwgx4ni0yeuq3xs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4wu7iwgx4ni0yeuq3xs.png" alt=" " width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is Infrastructure as Code magic&lt;/strong&gt; - you changed infrastructure by editing a text file!&lt;/p&gt;




&lt;h2&gt;
  
  
  🧹 Command 4: terraform destroy
&lt;/h2&gt;

&lt;p&gt;Always clean up resources you're not using (to avoid unexpected charges).&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;&lt;strong&gt;Terraform will show what it will delete:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# aws_s3_bucket.my_first_bucket will be destroyed&lt;/span&gt;
  &lt;span class="nx"&gt;-&lt;/span&gt; &lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"my_first_bucket"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&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;"terraform-first-bucket-yourname-2026"&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Plan&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;Do&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;really&lt;/span&gt; &lt;span class="nx"&gt;want&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;
  &lt;span class="nx"&gt;Enter&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Type &lt;code&gt;yes&lt;/code&gt; to confirm.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;aws_s3_bucket.my_first_bucket: Destroying...
aws_s3_bucket.my_first_bucket: Destruction complete after 1s

Destroy complete! Resources: 1 destroyed.
&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.amazonaws.com%2Fuploads%2Farticles%2F5y425ns24g2h7rm9n0u6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5y425ns24g2h7rm9n0u6.png" alt=" " width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verify in AWS Console&lt;/strong&gt; - your bucket is gone!&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%2Fr6mkfri1dqbr49sya0c1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6mkfri1dqbr49sya0c1.png" alt=" " width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎓 What You Just Learned
&lt;/h2&gt;

&lt;p&gt;Let's recap what you accomplished:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;The Terraform Workflow:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;init&lt;/code&gt; - Initialize project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;plan&lt;/code&gt; - Preview changes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apply&lt;/code&gt; - Create resources&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;destroy&lt;/code&gt; - Clean up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;HCL Basics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;terraform block (configuration)&lt;/li&gt;
&lt;li&gt;provider block (cloud provider)&lt;/li&gt;
&lt;li&gt;resource block (what to create)&lt;/li&gt;
&lt;li&gt;output block (display information)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;State Management:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;State file tracks resources&lt;/li&gt;
&lt;li&gt;Never edit state manually&lt;/li&gt;
&lt;li&gt;State enables change detection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;Real Infrastructure:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created actual AWS S3 bucket&lt;/li&gt;
&lt;li&gt;Modified existing resource&lt;/li&gt;
&lt;li&gt;Destroyed resources cleanly&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🐛 Common Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: Bucket Name Already Exists
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&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;Error: creating S3 Bucket: BucketAlreadyExists
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; S3 bucket names are globally unique. Change your bucket name to something more unique:&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;bucket&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-first-bucket-yourname-12345-2026"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Issue 2: Invalid Bucket Name
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&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;Error: invalid bucket name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; S3 bucket names must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be 3-63 characters long&lt;/li&gt;
&lt;li&gt;Use only lowercase letters, numbers, and hyphens&lt;/li&gt;
&lt;li&gt;Start with a letter or number&lt;/li&gt;
&lt;li&gt;Not use uppercase or underscores&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt; &lt;code&gt;My_Bucket_Name&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Good:&lt;/strong&gt; &lt;code&gt;my-bucket-name&lt;/code&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  Issue 3: AWS Credentials Not Found
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&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;Error: No valid credential sources found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Configure AWS credentials (from Article 2):&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;Enter your AWS Access Key ID and Secret Access Key.&lt;/p&gt;




&lt;h3&gt;
  
  
  Issue 4: Permission Denied
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Error:&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;Error: AccessDenied: Access Denied
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Your AWS user needs S3 permissions. Attach the &lt;code&gt;AmazonS3FullAccess&lt;/code&gt; policy to your IAM user in AWS Console.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Best Practices You Should Follow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Always Use Version Control
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;".terraform/"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"terraform.tfstate*"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"*.tfvars"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore
git add main.tf .gitignore
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add first Terraform resource"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Use Meaningful Names
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bad:&lt;/strong&gt;&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_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"b"&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;"bucket1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good:&lt;/strong&gt;&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_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"application_logs"&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;"myapp-logs-production-2026"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Always Add Tags
&lt;/h3&gt;

&lt;p&gt;Tags help with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost tracking&lt;/li&gt;
&lt;li&gt;Resource organization&lt;/li&gt;
&lt;li&gt;Automation&lt;/li&gt;
&lt;li&gt;Compliance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Minimum tags:&lt;/strong&gt;&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;tags&lt;/span&gt; &lt;span class="err"&gt;=&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;"Resource purpose"&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/staging/prod"&lt;/span&gt;
  &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Terraform"&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;"team-name"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Run Plan Before Apply
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Never skip &lt;code&gt;terraform plan&lt;/code&gt;!&lt;/strong&gt; It's your safety net.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Use Descriptive Outputs
&lt;/h3&gt;

&lt;p&gt;Outputs make it easy to get important information:&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;"bucket_name"&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;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;my_first_bucket&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;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The name of the S3 bucket"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔍 Understanding What Happened Behind the Scenes
&lt;/h2&gt;

&lt;p&gt;When you ran &lt;code&gt;terraform apply&lt;/code&gt;, here's what happened:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Terraform read your &lt;code&gt;main.tf&lt;/code&gt; file&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parsed the HCL syntax&lt;/li&gt;
&lt;li&gt;Understood you want an S3 bucket&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Terraform checked the state file&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Found it was empty (first run)&lt;/li&gt;
&lt;li&gt;Knew it needed to create the bucket&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Terraform called AWS API&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used your AWS credentials&lt;/li&gt;
&lt;li&gt;Made API call: &lt;code&gt;CreateBucket&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Set the tags with &lt;code&gt;PutBucketTagging&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AWS created the bucket&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generated unique bucket ID&lt;/li&gt;
&lt;li&gt;Returned bucket details&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Terraform updated state file&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Saved bucket information&lt;/li&gt;
&lt;li&gt;Recorded all attributes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Terraform displayed outputs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Showed the values you defined&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;This is the power of Infrastructure as Code&lt;/strong&gt; - complex API calls abstracted into simple, readable code!&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Challenge: Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Before moving to the next article, try these challenges:&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 1: Create Multiple Buckets
&lt;/h3&gt;

&lt;p&gt;Create 2 different S3 buckets in the same &lt;code&gt;main.tf&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hint:&lt;/strong&gt;&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_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"bucket_one"&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-first-bucket-yourname"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"bucket_two"&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-second-bucket-yourname"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Challenge 2: Use Different Region
&lt;/h3&gt;

&lt;p&gt;Change the provider region to &lt;code&gt;us-west-2&lt;/code&gt; and create a bucket there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 3: Add More Tags
&lt;/h3&gt;

&lt;p&gt;Add 3 more custom tags to your bucket (Project, CostCenter, Department).&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 4: Format Your Code
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;terraform fmt&lt;/code&gt; to automatically format your code:&lt;br&gt;
&lt;/p&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;h3&gt;
  
  
  Challenge 5: Validate Your Code
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;terraform validate&lt;/code&gt; to check for syntax errors:&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;h2&gt;
  
  
  📚 Additional Terraform Commands
&lt;/h2&gt;

&lt;p&gt;Beyond the core 4 commands, here are useful ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Format your code (auto-fix indentation)&lt;/span&gt;
terraform &lt;span class="nb"&gt;fmt&lt;/span&gt;

&lt;span class="c"&gt;# Validate syntax&lt;/span&gt;
terraform validate

&lt;span class="c"&gt;# Show current state&lt;/span&gt;
terraform show

&lt;span class="c"&gt;# List resources in state&lt;/span&gt;
terraform state list

&lt;span class="c"&gt;# Get detailed resource info&lt;/span&gt;
terraform state show aws_s3_bucket.my_first_bucket

&lt;span class="c"&gt;# View outputs without applying&lt;/span&gt;
terraform output

&lt;span class="c"&gt;# View specific output&lt;/span&gt;
terraform output bucket_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔗 Useful Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform AWS Provider Docs:&lt;/strong&gt; &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs" rel="noopener noreferrer"&gt;https://registry.terraform.io/providers/hashicorp/aws/latest/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3 Bucket Resource:&lt;/strong&gt; &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket" rel="noopener noreferrer"&gt;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HCL Syntax:&lt;/strong&gt; &lt;a href="https://developer.hashicorp.com/terraform/language/syntax/configuration" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/language/syntax/configuration&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform CLI Commands:&lt;/strong&gt; &lt;a href="https://developer.hashicorp.com/terraform/cli/commands" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/cli/commands&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎬 What's Next?
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;&lt;a href="https://dev.to/aws-builders/terraform-state-the-one-file-you-cant-afford-to-lose-33l4"&gt;Article 4&lt;/a&gt;: Understanding Terraform State&lt;/strong&gt;, we'll dive deeper into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How state files work internally&lt;/li&gt;
&lt;li&gt;State commands (&lt;code&gt;state list&lt;/code&gt;, &lt;code&gt;state show&lt;/code&gt;, &lt;code&gt;state mv&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Importing existing AWS resources&lt;/li&gt;
&lt;li&gt;State locking and remote state (preview)&lt;/li&gt;
&lt;li&gt;Recovering from state issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You'll learn:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why state is Terraform's most important file&lt;/li&gt;
&lt;li&gt;How to inspect and manipulate state safely&lt;/li&gt;
&lt;li&gt;What to do when state gets out of sync&lt;/li&gt;
&lt;li&gt;Preparing for team collaboration&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📝 Summary
&lt;/h2&gt;

&lt;p&gt;Today you learned the &lt;strong&gt;foundation of Terraform&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 4 Core Commands:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init     &lt;span class="c"&gt;# Get ready&lt;/span&gt;
terraform plan     &lt;span class="c"&gt;# Preview&lt;/span&gt;
terraform apply    &lt;span class="c"&gt;# Execute&lt;/span&gt;
terraform destroy  &lt;span class="c"&gt;# Cleanup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.tf&lt;/code&gt; files contain your infrastructure code&lt;/li&gt;
&lt;li&gt;State files track what Terraform created&lt;/li&gt;
&lt;li&gt;HCL syntax is simple and readable&lt;/li&gt;
&lt;li&gt;Always plan before applying&lt;/li&gt;
&lt;li&gt;Tags help organize resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You created real infrastructure with code!&lt;/strong&gt; No more clicking through AWS Console for simple tasks.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading. I hope this article provided practical insights and a clearer understanding of the topic.&lt;/p&gt;

&lt;p&gt;If you found this useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value
&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today
&lt;/li&gt;
&lt;li&gt;💾 Save it for your next optimization session
&lt;/li&gt;
&lt;li&gt;🔄 Share it with your team
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives are coming soon on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Operations&lt;/li&gt;
&lt;li&gt;GenAI &amp;amp; Agentic AI&lt;/li&gt;
&lt;li&gt;DevOps Automation&lt;/li&gt;
&lt;li&gt;Data &amp;amp; Platform Engineering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow along for weekly insights and hands-on guides.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts. Feel free to drop a comment or connect with me on:&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, reach out at:&lt;/p&gt;

&lt;p&gt;📧 &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Found this helpful? Share it with your team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⭐ Star the repo • 📖 Follow the series • 💬 Ask questions  &lt;/p&gt;

&lt;p&gt;Made by &lt;strong&gt;Sarvar Nadaf&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🌐 &lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;https://sarvarnadaf.com&lt;/a&gt;&lt;/p&gt;




</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Installing Terraform and Setting Up Your Environment</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Sat, 14 Mar 2026 20:22:21 +0000</pubDate>
      <link>https://forem.com/aws-builders/installing-terraform-and-setting-up-your-environment-1j9b</link>
      <guid>https://forem.com/aws-builders/installing-terraform-and-setting-up-your-environment-1j9b</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;

&lt;p&gt;Let's dive in and explore the fascinating world of cloud technology together! 🚀&lt;/p&gt;




&lt;p&gt;In this guide, we will walk through the step-by-step process of installing Terraform and preparing your local environment for infrastructure automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Learn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install Terraform on Linux (Ubuntu/Amazon Linux)&lt;/li&gt;
&lt;li&gt;Install AWS CLI&lt;/li&gt;
&lt;li&gt;Configure AWS credentials&lt;/li&gt;
&lt;li&gt;Verify your setup&lt;/li&gt;
&lt;li&gt;Set up VS Code for Terraform development&lt;/li&gt;
&lt;/ul&gt;




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

&lt;ul&gt;
&lt;li&gt;A Linux server or local machine (Ubuntu 20.04+ or Amazon Linux 2)&lt;/li&gt;
&lt;li&gt;AWS account with IAM user credentials&lt;/li&gt;
&lt;li&gt;Basic command line knowledge&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Install Terraform
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Ubuntu/Debian
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update package list&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update

&lt;span class="c"&gt;# Install required packages&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; gnupg software-properties-common wget

&lt;span class="c"&gt;# Add HashiCorp GPG key&lt;/span&gt;
wget &lt;span class="nt"&gt;-O-&lt;/span&gt; https://apt.releases.hashicorp.com/gpg | &lt;span class="se"&gt;\&lt;/span&gt;
gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;sudo tee&lt;/span&gt; /usr/share/keyrings/hashicorp-archive-keyring.gpg

&lt;span class="c"&gt;# Add HashiCorp repository&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
https://apt.releases.hashicorp.com &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;lsb_release &lt;span class="nt"&gt;-cs&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; main"&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/hashicorp.list

&lt;span class="c"&gt;# Update and install Terraform&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; terraform
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For Amazon Linux 2 (Recommended)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install yum-config-manager&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; yum-utils

&lt;span class="c"&gt;# Add HashiCorp repository&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum-config-manager &lt;span class="nt"&gt;--add-repo&lt;/span&gt; https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo

&lt;span class="c"&gt;# Install Terraform&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;terraform
&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.amazonaws.com%2Fuploads%2Farticles%2Fpr5jau1wbgkpmfqzdxfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpr5jau1wbgkpmfqzdxfw.png" alt=" " width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify Installation
&lt;/h3&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;&lt;strong&gt;Expected Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="nx"&gt;Terraform&lt;/span&gt; &lt;span class="nx"&gt;v1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;
&lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;linux_amd64&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.amazonaws.com%2Fuploads%2Farticles%2F2b7825615cromvw6n8an.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2b7825615cromvw6n8an.png" alt=" " width="687" height="124"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Install AWS CLI (Recommended)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Ubuntu/Debian
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download AWS CLI installer&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"awscliv2.zip"&lt;/span&gt;

&lt;span class="c"&gt;# Install unzip if not present&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; unzip

&lt;span class="c"&gt;# Unzip the installer&lt;/span&gt;
unzip awscliv2.zip

&lt;span class="c"&gt;# Run the installer&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./aws/install

&lt;span class="c"&gt;# Clean up&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; aws awscliv2.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For Amazon Linux 2
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download and install&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"awscliv2.zip"&lt;/span&gt;
unzip awscliv2.zip
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./aws/install
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; aws awscliv2.zip
&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.amazonaws.com%2Fuploads%2Farticles%2Fk998tb6sw6d63275t5xq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk998tb6sw6d63275t5xq.png" alt=" " width="800" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify Installation
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected Output:&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;aws-cli/2.x.x Python/3.x.x Linux/x.x.x
&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.amazonaws.com%2Fuploads%2Farticles%2F6h4865pqpom0nurrsac9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6h4865pqpom0nurrsac9.png" alt=" " width="800" height="52"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Create IAM User for Terraform
&lt;/h2&gt;

&lt;h3&gt;
  
  
  In AWS Console:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to IAM → Users → Create User&lt;/li&gt;
&lt;li&gt;Username: &lt;code&gt;terraform&lt;/code&gt; (or your preferred name)&lt;/li&gt;
&lt;li&gt;Select "Provide user access to the AWS Management Console" (optional)&lt;/li&gt;
&lt;li&gt;Attach policies: &lt;code&gt;AdministratorAccess&lt;/code&gt; (for learning; use restricted policies in production)&lt;/li&gt;
&lt;li&gt;Create user&lt;/li&gt;
&lt;li&gt;Go to Security Credentials → Create Access Key&lt;/li&gt;
&lt;li&gt;Select "Command Line Interface (CLI)"&lt;/li&gt;
&lt;li&gt;Download or copy:

&lt;ul&gt;
&lt;li&gt;Access Key ID&lt;/li&gt;
&lt;li&gt;Secret Access Key&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;&lt;strong&gt;⚠️ Important:&lt;/strong&gt; Never share or commit these credentials to version control!&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%2Fvt33fk0k0w9jkw4vefw2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvt33fk0k0w9jkw4vefw2.png" alt=" " width="800" height="283"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Configure AWS Credentials
&lt;/h2&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;&lt;strong&gt;You'll be prompted for:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;AWS&lt;/span&gt; &lt;span class="err"&gt;Access&lt;/span&gt; &lt;span class="err"&gt;Key&lt;/span&gt; &lt;span class="err"&gt;ID&lt;/span&gt; &lt;span class="err"&gt;[None]:&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;YOUR_ACCESS_KEY_ID&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;AWS&lt;/span&gt; &lt;span class="err"&gt;Secret&lt;/span&gt; &lt;span class="err"&gt;Access&lt;/span&gt; &lt;span class="err"&gt;Key&lt;/span&gt; &lt;span class="err"&gt;[None]:&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;YOUR_SECRET_ACCESS_KEY&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;Default&lt;/span&gt; &lt;span class="err"&gt;region&lt;/span&gt; &lt;span class="err"&gt;name&lt;/span&gt; &lt;span class="err"&gt;[None]:&lt;/span&gt; &lt;span class="err"&gt;us-east-1&lt;/span&gt; &lt;span class="err"&gt;(or&lt;/span&gt; &lt;span class="err"&gt;your&lt;/span&gt; &lt;span class="err"&gt;preferred&lt;/span&gt; &lt;span class="err"&gt;region)&lt;/span&gt;
&lt;span class="err"&gt;Default&lt;/span&gt; &lt;span class="err"&gt;output&lt;/span&gt; &lt;span class="err"&gt;format&lt;/span&gt; &lt;span class="err"&gt;[None]:&lt;/span&gt; &lt;span class="err"&gt;json&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.amazonaws.com%2Fuploads%2Farticles%2Fid5p0yj1jioqe8eybdhl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fid5p0yj1jioqe8eybdhl.png" alt=" " width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify Configuration
&lt;/h3&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;&lt;strong&gt;Expected Output:&lt;/strong&gt;&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;"UserId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AIDASRZSGHJSDC6XXXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Account"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123456789012"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Arn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::123456789012:user/terraform"&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;h2&gt;
  
  
  Step 5: Set Up Your Working Directory
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create project directory&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/terraform-projects
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/terraform-projects

&lt;span class="c"&gt;# Create your first project folder&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-first-terraform
&lt;span class="nb"&gt;cd &lt;/span&gt;my-first-terraform
&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.amazonaws.com%2Fuploads%2Farticles%2Ffbw7nifbbqq3xbxul9e7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbw7nifbbqq3xbxul9e7.png" alt=" " width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: (Optional) Install VS Code with Terraform Extension
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install VS Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ubuntu/Debian&lt;/span&gt;
wget &lt;span class="nt"&gt;-qO-&lt;/span&gt; https://packages.microsoft.com/keys/microsoft.asc | gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; packages.microsoft.gpg
&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; root &lt;span class="nt"&gt;-g&lt;/span&gt; root &lt;span class="nt"&gt;-m&lt;/span&gt; 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg
&lt;span class="nb"&gt;sudo &lt;/span&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" &amp;gt; /etc/apt/sources.list.d/vscode.list'&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Terraform Extension
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open VS Code&lt;/li&gt;
&lt;li&gt;Go to Extensions (Ctrl+Shift+X)&lt;/li&gt;
&lt;li&gt;Search for "HashiCorp Terraform"&lt;/li&gt;
&lt;li&gt;Click Install&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Extension Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syntax highlighting&lt;/li&gt;
&lt;li&gt;Auto-completion&lt;/li&gt;
&lt;li&gt;Formatting (terraform fmt)&lt;/li&gt;
&lt;li&gt;Validation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 7: Test Your Setup
&lt;/h2&gt;

&lt;p&gt;Create a simple test file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; test.tf &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
terraform {
  required_version = "&amp;gt;= 1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&amp;gt; 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

# This is just a test - we won't create any resources yet
output "account_id" {
  value = data.aws_caller_identity.current.account_id
}

data "aws_caller_identity" "current" {}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run Terraform commands:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize Terraform&lt;/span&gt;
terraform init

&lt;span class="c"&gt;# Validate configuration&lt;/span&gt;
terraform validate

&lt;span class="c"&gt;# See what would happen (no resources created)&lt;/span&gt;
terraform plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected Output:&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 has been successfully initialized!
Success! The configuration is valid.
Changes to Outputs:
  + account_id = "123456789012"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Clean up test file:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;test.tf
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; .terraform .terraform.lock.hcl
&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.amazonaws.com%2Fuploads%2Farticles%2F0orvrxuu1ubr4s20lipo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0orvrxuu1ubr4s20lipo.png" alt=" " width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Troubleshooting Common Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: "terraform: command not found"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Add Terraform to PATH or reinstall&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue 2: "Unable to locate credentials"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Run &lt;code&gt;aws configure&lt;/code&gt; again and verify credentials&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue 3: "Error: No valid credential sources found"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Check &lt;code&gt;~/.aws/credentials&lt;/code&gt; file exists and has correct format&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue 4: Permission denied errors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Verify IAM user has necessary permissions&lt;/p&gt;




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

&lt;p&gt;In the next article, we'll:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create our first AWS resource (S3 bucket)&lt;/li&gt;
&lt;li&gt;Understand Terraform workflow (init, plan, apply, destroy)&lt;/li&gt;
&lt;li&gt;Learn about Terraform state&lt;/li&gt;
&lt;li&gt;Explore basic Terraform syntax&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;✅ Terraform is installed and working&lt;br&gt;
✅ AWS CLI is configured with credentials&lt;br&gt;
✅ You can verify your AWS identity&lt;br&gt;
✅ Your development environment is ready&lt;br&gt;
✅ You understand the basic Terraform commands&lt;/p&gt;




&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.hashicorp.com/terraform/docs" rel="noopener noreferrer"&gt;Terraform Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cli/" rel="noopener noreferrer"&gt;AWS CLI Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs" rel="noopener noreferrer"&gt;Terraform AWS Provider&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Next Article:&lt;/strong&gt; &lt;a href="https://dev.to/aws-builders/your-first-infrastructure-as-code-in-four-commands-46ep"&gt;Part 3: Provisioning Your First AWS Resource&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading. I hope this article provided practical insights and a clearer understanding of the topic.&lt;/p&gt;

&lt;p&gt;If you found this useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value
&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today
&lt;/li&gt;
&lt;li&gt;💾 Save it for your next optimization session
&lt;/li&gt;
&lt;li&gt;🔄 Share it with your team
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives are coming soon on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Operations&lt;/li&gt;
&lt;li&gt;GenAI &amp;amp; Agentic AI&lt;/li&gt;
&lt;li&gt;DevOps Automation&lt;/li&gt;
&lt;li&gt;Data &amp;amp; Platform Engineering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow along for weekly insights and hands-on guides.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts. Feel free to drop a comment or connect with me on:&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, reach out at:&lt;/p&gt;

&lt;p&gt;📧 &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Found this helpful? Share it with your team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⭐ Star the repo • 📖 Follow the series • 💬 Ask questions  &lt;/p&gt;

&lt;p&gt;Made by &lt;strong&gt;Sarvar Nadaf&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🌐 &lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;https://sarvarnadaf.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Why Every Developer Should Learn Terraform in 2026 (And How to Start)</title>
      <dc:creator>Sarvar Nadaf</dc:creator>
      <pubDate>Fri, 13 Mar 2026 23:54:58 +0000</pubDate>
      <link>https://forem.com/aws-builders/why-every-developer-should-learn-terraform-in-2026-and-how-to-start--4fk0</link>
      <guid>https://forem.com/aws-builders/why-every-developer-should-learn-terraform-in-2026-and-how-to-start--4fk0</guid>
      <description>&lt;p&gt;👋 Hey there, tech enthusiasts! &lt;/p&gt;

&lt;p&gt;I'm Sarvar, a Cloud Architect with a passion for transforming complex technological challenges into elegant solutions. With extensive experience spanning Cloud Operations (AWS &amp;amp; Azure), Data Operations, Analytics, DevOps, and Generative AI, I've had the privilege of architecting solutions for global enterprises that drive real business impact. Through this article series, I'm excited to share practical insights, best practices, and hands-on experiences from my journey in the tech world. Whether you're a seasoned professional or just starting out, I aim to break down complex concepts into digestible pieces that you can apply in your projects.&lt;/p&gt;

&lt;p&gt;Let's dive in and explore the fascinating world of cloud technology together! 🚀&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The best time to learn Infrastructure as Code was 5 years ago. The second best time is now."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🎯 Why You're Here
&lt;/h2&gt;

&lt;p&gt;If you're reading this, chances are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're tired of manually clicking through AWS console for hours&lt;/li&gt;
&lt;li&gt;You've accidentally deleted a production server and wished you had a backup "recipe"&lt;/li&gt;
&lt;li&gt;Your team struggles to replicate environments consistently&lt;/li&gt;
&lt;li&gt;You want to level up your DevOps skills and increase your market value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Good news:&lt;/strong&gt; You're in the right place. This series will take you from zero to confidently managing cloud infrastructure with code.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Old Way: Manual Infrastructure Management
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Painful Reality
&lt;/h3&gt;

&lt;p&gt;Imagine this scenario (maybe you've lived it):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monday Morning:&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;Boss: "We need a new staging environment by EOD."
You: *Opens AWS Console*
     *Clicks through 47 different screens*
     *Creates VPC, subnets, security groups, EC2 instances...*
     *Takes 4 hours*
You: "Done! "
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tuesday Morning:&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;Boss: "Great! Now create the same setup for production."
You: *Realizes you forgot what you clicked*
     *Tries to remember the configuration*
     *Spends 5 hours recreating it*
     *Something is different but you're not sure what*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Wednesday Morning:&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;Boss: "The staging environment crashed. Can you rebuild it?"
You: *Panic intensifies* 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problems with Manual Infrastructure:
&lt;/h3&gt;

&lt;p&gt;❌ &lt;strong&gt;No Documentation&lt;/strong&gt; - "How did I configure that security group again?"&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Human Errors&lt;/strong&gt; - One wrong click = production down&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Time-Consuming&lt;/strong&gt; - Hours of repetitive clicking&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Not Reproducible&lt;/strong&gt; - Each environment is slightly different&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;No Version Control&lt;/strong&gt; - Can't rollback changes&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Team Collaboration Nightmare&lt;/strong&gt; - "Who changed the firewall rules?"&lt;br&gt;&lt;br&gt;
❌ &lt;strong&gt;Disaster Recovery&lt;/strong&gt; - If it's gone, it's GONE  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sound familiar?&lt;/strong&gt; This is where Infrastructure as Code (IaC) comes to the rescue.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 The Modern Way: Infrastructure as Code (IaC)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is Infrastructure as Code?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Simple Definition:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Infrastructure as Code means managing and provisioning your servers, networks, and cloud resources using &lt;strong&gt;code files&lt;/strong&gt; instead of manual processes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it like this:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Traditional Way:&lt;/strong&gt; Following a recipe in your head (error-prone, not shareable)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IaC Way:&lt;/strong&gt; Writing down the recipe in a cookbook (repeatable, shareable, version-controlled)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The IaC Approach:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="nx"&gt;You&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Writes&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;configuration&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="nx"&gt;minutes&lt;/span&gt;&lt;span class="err"&gt;)*&lt;/span&gt;
     &lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&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;ami&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-12345678"&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;span class="nx"&gt;You&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Runs&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;
     &lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="nx"&gt;apply&lt;/span&gt;

&lt;span class="nx"&gt;Terraform&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Creates&lt;/span&gt; &lt;span class="nx"&gt;entire&lt;/span&gt; &lt;span class="nx"&gt;infrastructure&lt;/span&gt; &lt;span class="nx"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="nx"&gt;minutes&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;
           &lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="nx"&gt;VPC&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt;
           &lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="nx"&gt;Subnets&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt;
           &lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="nx"&gt;Security&lt;/span&gt; &lt;span class="nx"&gt;groups&lt;/span&gt; &lt;span class="nx"&gt;configured&lt;/span&gt;
           &lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="nx"&gt;EC2&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="nx"&gt;launched&lt;/span&gt;
           &lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="nx"&gt;Everything&lt;/span&gt; &lt;span class="nx"&gt;documented&lt;/span&gt; &lt;span class="nx"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Benefits of IaC:
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;Version Control&lt;/strong&gt; - Track every change with Git&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Reproducible&lt;/strong&gt; - Same code = Same infrastructure, every time&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Fast&lt;/strong&gt; - Deploy in minutes, not hours&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Documented&lt;/strong&gt; - Your code IS your documentation&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Collaborative&lt;/strong&gt; - Team can review changes before applying&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Disaster Recovery&lt;/strong&gt; - Rebuild everything with one command&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Cost Savings&lt;/strong&gt; - Automate, optimize, and destroy unused resources easily  &lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 Enter Terraform: Your Infrastructure Automation Superpower
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is Terraform?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Terraform&lt;/strong&gt; is an open-source Infrastructure as Code tool created by HashiCorp that lets you define, provision, and manage cloud infrastructure using simple, human-readable configuration files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Terraform? (Not CloudFormation, Ansible, or Others)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Cloud-Agnostic&lt;/strong&gt; 🌍
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Works with AWS, Azure, GCP, and 3000+ providers&lt;/li&gt;
&lt;li&gt;Not locked into one cloud vendor&lt;/li&gt;
&lt;li&gt;Manage multi-cloud infrastructure from one tool&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Declarative Syntax&lt;/strong&gt; 📝
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# You declare WHAT you want, not HOW to create it&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"my_bucket"&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-awesome-bucket"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;# Terraform figures out the steps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. &lt;strong&gt;State Management&lt;/strong&gt; 🗂️
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Terraform tracks what's deployed&lt;/li&gt;
&lt;li&gt;Knows what changed and what needs updating&lt;/li&gt;
&lt;li&gt;Prevents configuration drift&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;Plan Before Apply&lt;/strong&gt; 🔍
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;terraform plan
&lt;span class="c"&gt;# Shows you EXACTLY what will change before you apply&lt;/span&gt;
&lt;span class="c"&gt;# No surprises, no accidents&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. &lt;strong&gt;Massive Ecosystem&lt;/strong&gt; 🌐
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;3000+ providers (AWS, Kubernetes, GitHub, Datadog, etc.)&lt;/li&gt;
&lt;li&gt;Huge community support&lt;/li&gt;
&lt;li&gt;Thousands of pre-built modules&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Terraform vs Other Tools
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Terraform&lt;/th&gt;
&lt;th&gt;CloudFormation&lt;/th&gt;
&lt;th&gt;Ansible&lt;/th&gt;
&lt;th&gt;Pulumi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-Cloud&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ AWS Only&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Hard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Language&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;HCL (Simple)&lt;/td&gt;
&lt;td&gt;JSON/YAML&lt;/td&gt;
&lt;td&gt;YAML&lt;/td&gt;
&lt;td&gt;Real Programming Languages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Huge&lt;/td&gt;
&lt;td&gt;Large&lt;/td&gt;
&lt;td&gt;Huge&lt;/td&gt;
&lt;td&gt;Growing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Infrastructure&lt;/td&gt;
&lt;td&gt;AWS-only projects&lt;/td&gt;
&lt;td&gt;Configuration Management&lt;/td&gt;
&lt;td&gt;Developers who prefer code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Bottom Line:&lt;/strong&gt; Terraform is the industry standard for multi-cloud infrastructure automation.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Real-World Use Cases: Where Terraform Shines
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Multi-Environment Management&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Same code → Different variables → Dev, Staging, Prod environments
No manual errors, perfect consistency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Disaster Recovery&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Server crashed? Region down?
Run: terraform apply
Infrastructure restored &lt;span class="k"&gt;in &lt;/span&gt;minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;strong&gt;Cost Optimization&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Destroy dev environment after work hours&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;terraform destroy &lt;span class="nt"&gt;-target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;aws_instance.dev_servers

&lt;span class="c"&gt;# Recreate next morning&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;terraform apply

Savings: &lt;span class="nv"&gt;$500&lt;/span&gt;/month on unused resources
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. &lt;strong&gt;Team Collaboration&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer: Creates pull request with infrastructure changes
Team: Reviews the terraform plan
Manager: Approves
CI/CD: Automatically applies changes
Everyone: Knows exactly what changed and when
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. &lt;strong&gt;Compliance &amp;amp; Auditing&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Every infrastructure change is:
- Version controlled in Git
- Reviewed and approved
- Documented automatically
- Auditable for compliance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🏆 Why Learning Terraform Will Boost Your Career
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Market Demand 📈
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Job Postings with "Terraform":&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2020: 15,000 jobs&lt;/li&gt;
&lt;li&gt;2024: 85,000+ jobs&lt;/li&gt;
&lt;li&gt;2026: Still growing rapidly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Average Salary Increase:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DevOps Engineer without IaC: $90K&lt;/li&gt;
&lt;li&gt;DevOps Engineer with Terraform: $120K+&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;That's a $30K+ difference!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Skills You'll Gain 🎓
&lt;/h3&gt;

&lt;p&gt;By learning Terraform, you'll also learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Cloud architecture (AWS, Azure, GCP)&lt;/li&gt;
&lt;li&gt;✅ Infrastructure best practices&lt;/li&gt;
&lt;li&gt;✅ Version control workflows&lt;/li&gt;
&lt;li&gt;✅ CI/CD pipelines&lt;/li&gt;
&lt;li&gt;✅ Security and compliance&lt;/li&gt;
&lt;li&gt;✅ Cost optimization strategies&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Career Paths 🚀
&lt;/h3&gt;

&lt;p&gt;Terraform opens doors to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevOps Engineer&lt;/strong&gt; - Automate everything&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Architect&lt;/strong&gt; - Design scalable systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Site Reliability Engineer (SRE)&lt;/strong&gt; - Ensure uptime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform Engineer&lt;/strong&gt; - Build internal platforms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure Engineer&lt;/strong&gt; - Manage cloud resources&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚦 Prerequisites: What You Need to Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Required ✅
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Basic Command Line Knowledge&lt;/strong&gt; - Know how to navigate directories, run commands&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Account&lt;/strong&gt; - Free tier is enough (&lt;a href="https://aws.amazon.com/free/" rel="noopener noreferrer"&gt;Create one here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Willingness to Learn&lt;/strong&gt; - That's it!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Nice to Have (But Not Required) 💡
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Basic understanding of cloud concepts (we'll explain as we go)&lt;/li&gt;
&lt;li&gt;Git basics (we'll cover what you need)&lt;/li&gt;
&lt;li&gt;Any programming experience (helpful but not necessary)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What You DON'T Need ❌
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;❌ DevOps experience&lt;/li&gt;
&lt;li&gt;❌ AWS certification&lt;/li&gt;
&lt;li&gt;❌ Programming expertise&lt;/li&gt;
&lt;li&gt;❌ Expensive tools or subscriptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you can open a terminal and follow instructions, you can learn Terraform!&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎬 How to Follow This Series
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Bookmark This Series
&lt;/h3&gt;

&lt;p&gt;📖 &lt;strong&gt;dev.to Series:&lt;/strong&gt; &lt;a href="https://dev.to/sarvar_04/series/36958"&gt;https://dev.to/sarvar_04/series/36958&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Star the GitHub Repository
&lt;/h3&gt;

&lt;p&gt;⭐ &lt;strong&gt;GitHub Repo:&lt;/strong&gt; &lt;a href="https://github.com/simplynadaf/terraform-by-sarvar" rel="noopener noreferrer"&gt;https://github.com/simplynadaf/terraform-by-sarvar&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All code examples are here&lt;/li&gt;
&lt;li&gt;Tested and ready to use&lt;/li&gt;
&lt;li&gt;Updated with each article&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Set Up Your Environment
&lt;/h3&gt;

&lt;p&gt;👉 &lt;strong&gt;Next Article:&lt;/strong&gt; &lt;a href="https://dev.to/sarvar_04/installing-terraform-and-setting-up-your-environment-1j9b"&gt;Installation &amp;amp; Setup&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Terraform&lt;/li&gt;
&lt;li&gt;Configure AWS CLI&lt;/li&gt;
&lt;li&gt;Verify your setup&lt;/li&gt;
&lt;li&gt;Ready to write your first Terraform code!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Join the Community
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;💬 Ask questions in &lt;a href="https://github.com/simplynadaf/terraform-by-sarvar/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔗 Connect on &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📧 Email: &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎯 Your Learning Path Starts Now
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Happens Next?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;In the next article&lt;/strong&gt;, you'll:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;✅ Install Terraform on your machine (Linux/Mac/Windows)&lt;/li&gt;
&lt;li&gt;✅ Set up AWS CLI and credentials&lt;/li&gt;
&lt;li&gt;✅ Configure your development environment&lt;/li&gt;
&lt;li&gt;✅ Run your first Terraform command&lt;/li&gt;
&lt;li&gt;✅ Verify everything is working&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Time Investment:&lt;/strong&gt; 30 minutes&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Difficulty:&lt;/strong&gt; Beginner-friendly&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Result:&lt;/strong&gt; Ready to write Terraform code!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Journey Ahead
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Week 1-2:  Foundation (Articles 1-3)
           ↓
Week 3-4:  Intermediate Concepts (Articles 4-8)
           ↓
Week 5-6:  Advanced Techniques (Articles 9-15)
           ↓
Result:    Production-Ready Terraform Skills 🎉
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💭 Final Thoughts: Why Start Today?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Infrastructure Revolution is Here
&lt;/h3&gt;

&lt;p&gt;Companies are moving to cloud at an unprecedented rate. &lt;strong&gt;Infrastructure as Code is no longer optional it's expected.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Best Investment You Can Make
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;⏰ &lt;strong&gt;Time:&lt;/strong&gt; 6-8 weeks of learning&lt;/li&gt;
&lt;li&gt;💰 &lt;strong&gt;Cost:&lt;/strong&gt; Free (just AWS free tier)&lt;/li&gt;
&lt;li&gt;📈 &lt;strong&gt;Return:&lt;/strong&gt; Career advancement, higher salary, in-demand skills&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  You're Not Alone
&lt;/h3&gt;

&lt;p&gt;Thousands of developers have learned Terraform and transformed their careers. You're joining a massive, supportive community.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Hardest Step is the First One
&lt;/h3&gt;

&lt;p&gt;You've already taken it by reading this article. Now keep the momentum going!&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Resources &amp;amp; Links
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Official Documentation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.hashicorp.com/terraform/docs" rel="noopener noreferrer"&gt;Terraform Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/free/" rel="noopener noreferrer"&gt;AWS Free Tier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://registry.terraform.io/" rel="noopener noreferrer"&gt;Terraform Registry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  This Series
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;📖 &lt;strong&gt;Series Home:&lt;/strong&gt; &lt;a href="https://dev.to/sarvar_04/series/36958"&gt;https://dev.to/sarvar_04/series/36958&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;strong&gt;Code Repository:&lt;/strong&gt; &lt;a href="https://github.com/simplynadaf/terraform-by-sarvar" rel="noopener noreferrer"&gt;https://github.com/simplynadaf/terraform-by-sarvar&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Infrastructure as Code isn't just a trend it's the foundation of modern cloud operations. Terraform has become the industry standard, and learning it will open countless opportunities in your career.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Every expert was once a beginner&lt;/li&gt;
&lt;li&gt;The best way to learn is by doing&lt;/li&gt;
&lt;li&gt;This series will guide you every step of the way&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In the next article&lt;/strong&gt;, we'll get your hands dirty by installing Terraform and setting up your development environment. You'll run your first Terraform command and be ready to start building real infrastructure.&lt;/p&gt;




&lt;h2&gt;
  
  
  👉 What's Next?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Next Article:&lt;/strong&gt; &lt;a href="https://dev.to/sarvar_04/installing-terraform-and-setting-up-your-environment-1j9b"&gt;Part 2: Installing Terraform and Setting Up Your Environment&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next article, you'll learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ How to install Terraform on Linux, Mac, and Windows&lt;/li&gt;
&lt;li&gt;✅ Setting up AWS CLI and credentials&lt;/li&gt;
&lt;li&gt;✅ Configuring VS Code for Terraform development&lt;/li&gt;
&lt;li&gt;✅ Running your first Terraform commands&lt;/li&gt;
&lt;li&gt;✅ Verifying your setup is working correctly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;See you in the next article! Let's start building! 🚀&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Thank you for reading. I hope this article provided practical insights and a clearer understanding of the topic.&lt;/p&gt;

&lt;p&gt;If you found this useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❤️ Like if it added value
&lt;/li&gt;
&lt;li&gt;🦄 Unicorn if you’re applying it today
&lt;/li&gt;
&lt;li&gt;💾 Save it for your next optimization session
&lt;/li&gt;
&lt;li&gt;🔄 Share it with your team
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What’s Next
&lt;/h2&gt;

&lt;p&gt;More deep dives are coming soon on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Operations&lt;/li&gt;
&lt;li&gt;GenAI &amp;amp; Agentic AI&lt;/li&gt;
&lt;li&gt;DevOps Automation&lt;/li&gt;
&lt;li&gt;Data &amp;amp; Platform Engineering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow along for weekly insights and hands-on guides.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Portfolio &amp;amp; Work
&lt;/h2&gt;

&lt;p&gt;You can explore my full body of work, certifications, architecture projects, and technical articles here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;Visit My Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Services I Offer
&lt;/h2&gt;

&lt;p&gt;If you're looking for hands-on guidance or collaboration, I provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Architecture Consulting (AWS / Azure)&lt;/li&gt;
&lt;li&gt;DevSecOps &amp;amp; Automation Design&lt;/li&gt;
&lt;li&gt;FinOps Optimization Reviews&lt;/li&gt;
&lt;li&gt;Technical Writing (Cloud, DevOps, GenAI)&lt;/li&gt;
&lt;li&gt;Product &amp;amp; Architecture Reviews&lt;/li&gt;
&lt;li&gt;Mentorship &amp;amp; 1:1 Technical Guidance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts. Feel free to drop a comment or connect with me on:&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.linkedin.com/in/sarvar04/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For collaborations, consulting, or technical discussions, reach out at:&lt;/p&gt;

&lt;p&gt;📧 &lt;a href="mailto:simplynadaf@gmail.com"&gt;simplynadaf@gmail.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Found this helpful? Share it with your team.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⭐ Star the repo • 📖 Follow the series • 💬 Ask questions  &lt;/p&gt;

&lt;p&gt;Made by &lt;strong&gt;Sarvar Nadaf&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
🌐 &lt;a href="https://sarvarnadaf.com" rel="noopener noreferrer"&gt;https://sarvarnadaf.com&lt;/a&gt;&lt;/p&gt;




</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
