<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ankitgadling</title>
    <description>The latest articles on DEV Community by ankitgadling (@ankitgadling).</description>
    <link>https://dev.to/ankitgadling</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%2F1191641%2F4ab67d9d-d25a-4394-b5bb-d7d1d2bbc8dc.jpeg</url>
      <title>DEV Community: ankitgadling</title>
      <link>https://dev.to/ankitgadling</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ankitgadling"/>
    <language>en</language>
    <item>
      <title>Day 9 - Protect resources from accidental deletion.</title>
      <dc:creator>ankitgadling</dc:creator>
      <pubDate>Wed, 10 Dec 2025 17:08:19 +0000</pubDate>
      <link>https://dev.to/ankitgadling/day-9-protect-resources-from-accidental-deletion-3od3</link>
      <guid>https://dev.to/ankitgadling/day-9-protect-resources-from-accidental-deletion-3od3</guid>
      <description>&lt;p&gt;Managing resources using Terraform, we sometimes need to protect our resources from accidental deletion.&lt;/p&gt;

&lt;p&gt;This is our day 9 of learning Terraform with AWS. Whenever we are managing resources using Terraform, we can destroy all the resources with a single command (&lt;code&gt;terraform destroy&lt;/code&gt;). However, there are certain resources we do &lt;em&gt;not&lt;/em&gt; want to delete such as databases or S3 buckets with important data.&lt;/p&gt;

&lt;p&gt;To protect these resources, Terraform provides lifecycle meta-arguments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let’s see how it works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Example 1: Preventing downtime - &lt;code&gt;create_before_destroy&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Consider you want to deploy an API on EC2 instances that sit behind a load balancer.&lt;br&gt;
If you destroy the resource, the API will face downtime until a new instance is created again. This can cause business loss, and users may lose trust if it happens frequently.&lt;/p&gt;

&lt;p&gt;To prevent downtime, we can use the lifecycle meta-argument &lt;code&gt;create_before_destroy&lt;/code&gt;, which tells Terraform to &lt;strong&gt;create a new resource before destroying the old one&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"api_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;"t3.micro"&lt;/span&gt;

  &lt;span class="nx"&gt;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;create_before_destroy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="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;
  
  
  Example 2: Protecting critical resources - &lt;code&gt;prevent_destroy&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now consider a requirement to store compliance-related documents. You create an S3 bucket for this purpose.&lt;br&gt;
If this S3 bucket gets destroyed, all compliance documents will be lost.&lt;/p&gt;

&lt;p&gt;To avoid this, Terraform provides the &lt;code&gt;prevent_destroy&lt;/code&gt; argument.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"compliance_docs"&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-compliance-docs-bucket"&lt;/span&gt;

  &lt;span class="nx"&gt;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;prevent_destroy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Example 3: Ignoring externally managed changes - &lt;code&gt;ignore_changes&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Suppose your API experiences a sudden spike and you rely on autoscaling policies.&lt;br&gt;
If an Auto Scaling Group is created using Terraform with a default capacity, Terraform may later try to override changes made automatically by scaling policies. This can cause API performance issues.&lt;/p&gt;

&lt;p&gt;To prevent this, we tell Terraform that the capacity is managed outside Terraform, and it should ignore changes to that attribute. For this, we use &lt;code&gt;ignore_changes&lt;/code&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_autoscaling_group"&lt;/span&gt; &lt;span class="s2"&gt;"api_asg"&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;"api-asg"&lt;/span&gt;
  &lt;span class="nx"&gt;min_size&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;max_size&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;desired_capacity&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;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ignore_changes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;desired_capacity&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;h3&gt;
  
  
  Example 4: Triggering replacement on dependency changes - &lt;code&gt;replace_triggered_by&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Terraform also provides &lt;code&gt;replace_triggered_by&lt;/code&gt; in lifecycle meta-arguments, which is useful when you want to replace a resource when something else changes.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight 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;"app_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="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;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;replace_triggered_by&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;instance_type&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;app_sg&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Example 5: Validating input and output - &lt;code&gt;precondition&lt;/code&gt; and &lt;code&gt;postcondition&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;There are cases where we must validate inputs (like regions or environment constraints) or outputs (such as resource attributes after deployment).&lt;br&gt;
To handle these scenarios, Terraform provides &lt;code&gt;precondition&lt;/code&gt; and &lt;code&gt;postcondition&lt;/code&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;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="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;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;precondition&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;length&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="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&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 name must be longer than 3 characters."&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;postcondition&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;versioning&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;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;error_message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Versioning must be enabled for this bucket."&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;h2&gt;
  
  
  

  &lt;iframe src="https://www.youtube.com/embed/60tOSwpvldY"&gt;
  &lt;/iframe&gt;



&lt;/h2&gt;

</description>
      <category>devops</category>
      <category>tutorial</category>
      <category>terraform</category>
      <category>aws</category>
    </item>
    <item>
      <title>Day 8 - Terraform Meta-Arguments</title>
      <dc:creator>ankitgadling</dc:creator>
      <pubDate>Tue, 09 Dec 2025 17:51:57 +0000</pubDate>
      <link>https://dev.to/ankitgadling/day-8-terraform-meta-arguments-16c4</link>
      <guid>https://dev.to/ankitgadling/day-8-terraform-meta-arguments-16c4</guid>
      <description>&lt;p&gt;Whenever we create any resource using Terraform, whether it is an S3 bucket, an EC2 instance, or a security group, we have to pass certain arguments that are specific to the provider. For example, while creating an AWS S3 bucket, we must provide a bucket name, which is a provider-specific argument. Along with these arguments, Terraform also provides additional arguments that work across all resource types. These are known as meta-arguments. Meta-arguments allow us to add extra functionality on top of the normal provider arguments, such as creating multiple resources, controlling dependencies, or defining lifecycle rules.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Terraform Meta-Arguments
&lt;/h2&gt;

&lt;p&gt;Some of the most commonly used meta-arguments are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;count - With the help of count we can create multiple instances of the same resource.&lt;/li&gt;
&lt;li&gt;for_each - Allows you to create multiple resources based on a map or set, giving more flexibility than count.&lt;/li&gt;
&lt;li&gt;depends_on - It is used to define explicit dependency between resources.&lt;/li&gt;
&lt;li&gt;provider - Overrides which provider configuration to use for a particular resource.&lt;/li&gt;
&lt;li&gt;lifecycle - It helps in controlling resource behavior, like preventing deletion or ignoring certain changes.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How Meta-Arguments Help in Real Projects
&lt;/h2&gt;

&lt;p&gt;Let us consider a situation where we need to launch EC2 instances for testing, staging, and production environments. Instead of writing the same resource block multiple times, meta-arguments allow us to dynamically control how many EC2 instances to create.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Using count
&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;"ec2_count"&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="mi"&gt;3&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_instance"&lt;/span&gt; &lt;span class="s2"&gt;"my_ec2"&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;ec2_count&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-0c55b159cbfafe1f0"&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;

  &lt;span class="nx"&gt;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;"EC2-${count.index}"&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;What happens here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If ec2_count = 3, Terraform creates 3 EC2 instances.&lt;/li&gt;
&lt;li&gt;If tomorrow you want 5 instances, just change the variable. There is no need to modify the resource block.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is very helpful in environments where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The number of servers may change frequently&lt;/li&gt;
&lt;li&gt;Teams want to scale infrastructure quickly&lt;/li&gt;
&lt;li&gt;We need to replicate identical resources, for example security groups, IAM users, or EC2 instances&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%2Fz37p0v8f53zlo361yjj6.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%2Fz37p0v8f53zlo361yjj6.png" alt="count Meta-Argument"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Example Using for_each
&lt;/h2&gt;

&lt;p&gt;Suppose we want to create EC2 instances with different names or 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;"servers"&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;app&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;db&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.small"&lt;/span&gt;
    &lt;span class="nx"&gt;cache&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="p"&gt;}&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;"server"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;for_each&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;servers&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-0c55b159cbfafe1f0"&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;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates three EC2 instances with different roles and instance types without repeating any code.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq6h606d0jf32dfagdwf0.png" alt="for_each meta argument"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Example Using depends_on
&lt;/h2&gt;

&lt;p&gt;Sometimes Terraform automatically understands the order in which resources should be created based on references. However, there are situations where we need to manually define the dependency to ensure one resource is created before another.&lt;/p&gt;

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

&lt;p&gt;Suppose we want to create an EC2 instance, but only after a security group is fully created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_security_group"&lt;/span&gt; &lt;span class="s2"&gt;"ec2_sg"&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;"ec2-security-group"&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 SSH"&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;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="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="p"&gt;}&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;"my_ec2"&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-0c55b159cbfafe1f0"&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;

  &lt;span class="nx"&gt;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_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ec2_sg&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;"EC2-with-depends-on"&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%2Fjz0u8a96563vzvg3id0o.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%2Fjz0u8a96563vzvg3id0o.png" alt="depends_on Meta-Argument"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is depends_on useful?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ensures Terraform creates resources in the correct order&lt;/li&gt;
&lt;li&gt;Helps avoid runtime failures, for example EC2 launching before its security group exists&lt;/li&gt;
&lt;li&gt;Useful when resources do not have a direct reference but still require ordering&lt;/li&gt;
&lt;li&gt;Makes execution predictable and safer&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Meta-Arguments Are Important
&lt;/h2&gt;

&lt;p&gt;In real projects, meta-arguments help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce code duplication&lt;/li&gt;
&lt;li&gt;Improve scalability, making it easy to increase or decrease the number of resources&lt;/li&gt;
&lt;li&gt;Keep infrastructure DRY (Do Not Repeat Yourself)&lt;/li&gt;
&lt;li&gt;Provide flexible configurations&lt;/li&gt;
&lt;li&gt;Control resource behavior more effectively&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meta-arguments are one of the most powerful features in Terraform and they help make infrastructure more modular, maintainable, and scalable.&lt;/p&gt;

&lt;h2&gt;
  
  
  

  &lt;iframe src="https://www.youtube.com/embed/XMMsnkovNX4"&gt;
  &lt;/iframe&gt;



&lt;/h2&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>devops</category>
      <category>terraform</category>
      <category>aws</category>
    </item>
    <item>
      <title>Day 7 – Type Constraints in Terraform</title>
      <dc:creator>ankitgadling</dc:creator>
      <pubDate>Sun, 07 Dec 2025 17:45:31 +0000</pubDate>
      <link>https://dev.to/ankitgadling/day-7-type-constraints-in-terraform-2g2</link>
      <guid>https://dev.to/ankitgadling/day-7-type-constraints-in-terraform-2g2</guid>
      <description>&lt;p&gt;On day 5 we have seen the variables in action. Today we will be doing a deep dive into type constraints in Terraform. A Terraform variable has certain types: primitive, complex, and special. We will start with primitive first.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Primitive Types
&lt;/h2&gt;

&lt;p&gt;The word itself explains this type. Primitive means the basic ones, which include string, number, and bool.&lt;/p&gt;

&lt;h3&gt;
  
  
  String
&lt;/h3&gt;

&lt;p&gt;It can have any text value.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"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="nx"&gt;default&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Number
&lt;/h3&gt;

&lt;p&gt;Numeric values integers as well as floats.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"age"&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="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bool
&lt;/h3&gt;

&lt;p&gt;Boolean value (true/false).&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"is_enabled"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bool&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Complex Types
&lt;/h2&gt;

&lt;p&gt;Complex types are types that allow you to group multiple values.&lt;/p&gt;

&lt;h3&gt;
  
  
  List
&lt;/h3&gt;

&lt;p&gt;Its an ordered collection of values of the same type.&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_ids"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set
&lt;/h3&gt;

&lt;p&gt;Its a collection of unique values, also of the same type, but order does not matter.&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;"unique_tags"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tuple
&lt;/h3&gt;

&lt;p&gt;Its an ordered collection of values of different types.&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;"my_tuple"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Map
&lt;/h3&gt;

&lt;p&gt;Its a set of string keys with values of the same type.&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;"region_mapping"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Object
&lt;/h3&gt;

&lt;p&gt;Its a collection of attributes with different types, similar to a struct.&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;"server_config"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;cpu&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;prod&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bool&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Special Types
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Any
&lt;/h3&gt;

&lt;p&gt;Allows any data type Terraform will accept whatever is provided.&lt;br&gt;
Useful for flexible modules. We should avoid using it.&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;"input"&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;any&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Null
&lt;/h3&gt;

&lt;p&gt;It represents the absence of a value and is often used to trigger default behavior.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_type"&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="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform will use the default from the provider/resource when &lt;code&gt;null&lt;/code&gt; is passed.&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%2Fnebbx6kn7x5su3ntgoyu.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%2Fnebbx6kn7x5su3ntgoyu.png" alt="Type Constraints in Terraform"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How These Types Help in Real Terraform Projects
&lt;/h2&gt;




&lt;h3&gt;
  
  
  Strings for Naming Resources
&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;"environment"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;
&lt;span class="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;"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}-app-data"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change &lt;code&gt;environment&lt;/code&gt; once → everything updates.&lt;/p&gt;




&lt;h3&gt;
  
  
  Numbers for Scaling Resources
&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_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="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"server"&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="s2"&gt;"ami-123"&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Increase the number → Terraform creates more servers.&lt;/p&gt;




&lt;h3&gt;
  
  
  Booleans for Feature Toggles
&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;"monitoring_enabled"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bool&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"server"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;monitoring&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;monitoring_enabled&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Turn monitoring &lt;strong&gt;on/off&lt;/strong&gt; with a single variable.&lt;/p&gt;




&lt;h3&gt;
  
  
  Lists for Repeating Resources
&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;"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;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_subnet"&lt;/span&gt; &lt;span class="s2"&gt;"subnet"&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;length&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;availability_zones&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;az&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;availability_zones&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;cidr_block&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.${count.index}.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;Subnets automatically created across multiple AZs.&lt;/p&gt;




&lt;h3&gt;
  
  
  Maps for Centralized Tagging
&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;"tags"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="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;"dev"&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;"teamA"&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_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;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;tags&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manage all tags from one place.&lt;/p&gt;




&lt;h3&gt;
  
  
  Objects for Clean, Structured Config
&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;"config"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;region&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;monitoring&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;instance_count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;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;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;monitoring&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;instance_count&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="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;config&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  

  &lt;iframe src="https://www.youtube.com/embed/gu2oCJ9DQiQ"&gt;
  &lt;/iframe&gt;



&lt;/h2&gt;

&lt;p&gt;for more information checkout&lt;br&gt;
&lt;a href="https://github.com/ankitgadling/terraformwithaws/tree/main/day_7" rel="noopener noreferrer"&gt;https://github.com/ankitgadling/terraformwithaws/tree/main/day_7&lt;/a&gt;&lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
    </item>
    <item>
      <title>Day 6 - Terraform Project Structure Best Practices</title>
      <dc:creator>ankitgadling</dc:creator>
      <pubDate>Thu, 04 Dec 2025 17:46:10 +0000</pubDate>
      <link>https://dev.to/ankitgadling/day-6-terraform-project-structure-best-practices-4alc</link>
      <guid>https://dev.to/ankitgadling/day-6-terraform-project-structure-best-practices-4alc</guid>
      <description>&lt;p&gt;As I continue my Terraform with AWS learning journey, today’s focus was on one of the most underrated yet extremely important topics: how to properly structure a Terraform project. When you're getting started, it’s tempting to put all your &lt;code&gt;.tf&lt;/code&gt; files in a single folder and just make things “work.” And yes Terraform will still run. But as your infrastructure grows, poor structure quickly leads to chaos.&lt;/p&gt;

&lt;p&gt;On Day 6, I learned why project structure matters, the problems you face when you don’t manage it well, and the best practices recommended by Terraform to build clean, scalable, and maintainable infrastructure from day one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Project Structure Matters in Terraform
&lt;/h2&gt;

&lt;p&gt;Terraform is declarative and modular by design. Its power becomes clear when you start organizing infrastructure into reusable components, separating environments, and keeping configuration clean. Without a proper structure, your project becomes difficult to understand, debug, and scale.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cons of Not Having a Proper Terraform Project Structure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Hard to Maintain and Scale
&lt;/h3&gt;

&lt;p&gt;If everything sits in one directory, adding new components becomes painful. Small projects might survive a messy layout, but as soon as you expand add more VPCs, subnets, or services you’ll struggle to keep track of what belongs where.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Increased Risk of Mistakes
&lt;/h3&gt;

&lt;p&gt;A single misplaced variable or resource can affect your entire infrastructure. Without structure, you may accidentally update or destroy resources you didn’t intend to. Clear separation of modules and environments helps minimize such risks.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Poor Collaboration
&lt;/h3&gt;

&lt;p&gt;When working in a team, a disorganized Terraform setup creates confusion. Developers may overwrite each other's changes, misinterpret variable usage, or struggle to locate specific components.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Difficult Troubleshooting
&lt;/h3&gt;

&lt;p&gt;When Terraform state gets large and your files aren’t organized, troubleshooting becomes time-consuming. Clear file boundaries allow you to isolate issues faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Reusability Drops
&lt;/h3&gt;

&lt;p&gt;One of Terraform’s strengths is the ability to build reusable modules. Without structure, creating modules later becomes harder and requires refactoring.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices Recommended by Terraform
&lt;/h2&gt;

&lt;p&gt;HashiCorp provides guidelines and patterns to help you build a scalable Terraform setup from the beginning. Here are the key practices I learned today.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Separate Environments
&lt;/h3&gt;

&lt;p&gt;Use folders to separate dev, staging, and production. Each environment can have its own variables and backend configuration.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env/
   dev/
   staging/
   prod/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents accidental changes to production and provides clear isolation.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Maintain a Clear File Layout
&lt;/h3&gt;

&lt;p&gt;A standard Terraform directory commonly includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;main.tf&lt;/strong&gt; – core resources&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;variables.tf&lt;/strong&gt; – all input variables&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;outputs.tf&lt;/strong&gt; – outputs from your configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;providers.tf&lt;/strong&gt; – provider configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;terraform.tfvars&lt;/strong&gt; – environment-specific variable values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes onboarding easier because anyone can quickly understand where everything goes.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Follow Naming Conventions
&lt;/h3&gt;

&lt;p&gt;Consistent names make navigation easier. For example, naming resources like &lt;code&gt;app_vpc&lt;/code&gt; or &lt;code&gt;demo_s3_bucket&lt;/code&gt; helps avoid confusion between different stacks.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Keep Secrets Out of Your Code
&lt;/h3&gt;

&lt;p&gt;Use environment variables, AWS Secrets Manager, or Terraform Cloud variables. Never hard-code secrets inside &lt;code&gt;.tfvars&lt;/code&gt; or &lt;code&gt;.tf&lt;/code&gt; files.&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%2Fglbp7m70g1q7bqhwaan8.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%2Fglbp7m70g1q7bqhwaan8.png" alt="Terraform Project Structure"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Day 6 taught me that Terraform isn’t just about writing resources it’s about writing clean and organized infrastructure code. A well structured project saves time, reduces mistakes, improves collaboration, and allows you to scale with confidence. Setting up the right structure early is one of the best long term investments you can make in your infrastructure-as-code journey.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/QMsJholPkDY"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>devops</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day 5 - Terraform Variables</title>
      <dc:creator>ankitgadling</dc:creator>
      <pubDate>Wed, 03 Dec 2025 17:13:14 +0000</pubDate>
      <link>https://dev.to/ankitgadling/day-5-terraform-variables-3768</link>
      <guid>https://dev.to/ankitgadling/day-5-terraform-variables-3768</guid>
      <description>&lt;p&gt;Before exploring Terraform variables, let’s first understand what &lt;em&gt;variables&lt;/em&gt; are.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;variable&lt;/strong&gt; is simply something whose value can change. Variables are used to avoid hardcoding, improve reusability, enhance readability, and support modular design. Every programming language uses variables and Terraform is no different.&lt;/p&gt;

&lt;p&gt;Terraform also supports variables, and they can be categorized in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Based on purpose&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Based on value&lt;/strong&gt;&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%2F5q6jv0yc3mq8dfbdzdio.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%2F5q6jv0yc3mq8dfbdzdio.png" alt="Terraform Variables"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Input Variables
&lt;/h3&gt;

&lt;p&gt;Used to pass values into Terraform from users or external sources.&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 hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"region"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Output Variables
&lt;/h3&gt;

&lt;p&gt;Used to display or export values after &lt;code&gt;terraform apply&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 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;demo&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Local Values (locals)
&lt;/h3&gt;

&lt;p&gt;Used to simplify complex or repeated expressions.&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 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;env_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  String Concatenation in Terraform
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="s2"&gt;"${var.env}-bucket"&lt;/span&gt;

&lt;span class="s2"&gt;"${var.env}-bucket-${var.region}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Terraform Variable Precedence
&lt;/h2&gt;

&lt;p&gt;Terraform loads variables in the following order (LOW to HIGH precedence):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Precedence&lt;/th&gt;
&lt;th&gt;Source&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;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Default values in variables.tf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;lowest priority&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Environment variables&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;export TF_VAR_region="us-east-1"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;terraform.tfvars&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;auto-loaded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;terraform.tfvars.json&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;auto-loaded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;**.auto.tfvars / *.auto.tfvars.json&lt;/em&gt;*&lt;/td&gt;
&lt;td&gt;auto-loaded in alphabetical order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;-var and -var-file CLI flags&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;highest priority&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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%2Fgeylb6rvrbvzawik84iz.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%2Fgeylb6rvrbvzawik84iz.png" alt="Variable Precedance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Environment Variable
&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;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"dev"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ✔ Example CLI Variable
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply &lt;span class="nt"&gt;-var&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"env=dev"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✔ Example CLI Var File
&lt;/h3&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;"dev.tfvars"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Example: Creating an S3 Bucket Using env = dev
&lt;/h2&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;variables.tf&lt;/strong&gt;
&lt;/h2&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;"env"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;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;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="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"region"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;main.tf&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&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;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"demo"&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.env}-bucket-demo"&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_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;demo&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;terraform.tfvars (optional)&lt;/strong&gt;
&lt;/h2&gt;



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

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Run Commands&lt;/strong&gt;
&lt;/h2&gt;



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

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Resulting Bucket Name&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dev-bucket-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/V-2yC39BONc"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>devops</category>
      <category>terraform</category>
      <category>aws</category>
    </item>
    <item>
      <title>Day 4 - Terraform State File Management with Remote Backends (S3 Native Locking)</title>
      <dc:creator>ankitgadling</dc:creator>
      <pubDate>Thu, 27 Nov 2025 16:42:59 +0000</pubDate>
      <link>https://dev.to/ankitgadling/day-4-terraform-state-file-management-with-remote-backends-s3-native-locking-14f5</link>
      <guid>https://dev.to/ankitgadling/day-4-terraform-state-file-management-with-remote-backends-s3-native-locking-14f5</guid>
      <description>&lt;p&gt;Terraform relies on a &lt;strong&gt;state file&lt;/strong&gt; to understand the infrastructure it manages. Instead of constantly querying cloud providers which is slow, expensive, and inefficient Terraform stores the current state of your resources locally or remotely. This file acts as Terraform’s “source of truth,” enabling it to detect changes, manage dependencies, and apply updates safely.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Terraform State File?
&lt;/h2&gt;

&lt;p&gt;Terraform’s state file records the attributes and relationships of your deployed resources. It allows Terraform to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compare desired configuration vs. actual infrastructure&lt;/li&gt;
&lt;li&gt;Generate accurate execution plans&lt;/li&gt;
&lt;li&gt;Track dependencies between resources&lt;/li&gt;
&lt;li&gt;Enable collaboration across teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because Terraform relies heavily on this file, keeping it secure and consistent is critical.&lt;/p&gt;




&lt;h2&gt;
  
  
  State File Best Practices
&lt;/h2&gt;

&lt;p&gt;To avoid corruption, security risks, or inconsistent deployments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Never edit the state file manually&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use remote storage instead of local files&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable state locking&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Back up regularly&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use separate state files per environment&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restrict state file access&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encrypt in transit and at rest&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These practices ensure your infrastructure remains predictable and stable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Store State Files Remotely?
&lt;/h2&gt;

&lt;p&gt;Remote backends like AWS S3 provide several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration:&lt;/strong&gt; Team members share one state source&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Locking:&lt;/strong&gt; Prevents simultaneous modifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; IAM, encryption, and access controls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versioning:&lt;/strong&gt; Easy rollback and recovery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High availability:&lt;/strong&gt; Durable and reliable storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Local state works for learning, but teams need the reliability of remote backends.&lt;/p&gt;




&lt;h2&gt;
  
  
  AWS Remote Backend Overview
&lt;/h2&gt;

&lt;p&gt;A typical Terraform remote backend in AWS includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;S3 Bucket&lt;/strong&gt; - to store state files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3 Native State Locking&lt;/strong&gt; - available in Terraform 1.10+&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM Policies&lt;/strong&gt; - to control read/write access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Previously, DynamoDB tables were required for locking. Now, Terraform can use S3 alone.&lt;/p&gt;




&lt;h2&gt;
  
  
  S3 Native State Locking (Terraform 1.10+)
&lt;/h2&gt;

&lt;p&gt;Terraform 1.10 introduced &lt;strong&gt;S3-native state locking&lt;/strong&gt;, using AWS S3’s Conditional Writes (&lt;code&gt;If-None-Match&lt;/code&gt;). This allows Terraform to manage lock files directly in S3.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Terraform tries to create a lock file in S3.&lt;/li&gt;
&lt;li&gt;If the lock file already exists, S3 rejects the request.&lt;/li&gt;
&lt;li&gt;If not, Terraform acquires the lock.&lt;/li&gt;
&lt;li&gt;When the operation finishes, the lock file is deleted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This ensures only one Terraform operation can modify the state at a time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Locking Prevents State Corruption
&lt;/h2&gt;

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

&lt;p&gt;Without locking, two engineers could run &lt;code&gt;terraform apply&lt;/code&gt; simultaneously, causing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Corrupted state&lt;/li&gt;
&lt;li&gt;Duplicate resources&lt;/li&gt;
&lt;li&gt;Missing infrastructure&lt;/li&gt;
&lt;li&gt;Unpredictable environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With S3 native locking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only one operation proceeds&lt;/li&gt;
&lt;li&gt;Others are blocked with a “state is locked” message&lt;/li&gt;
&lt;li&gt;State remains consistent and protected&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/YsEdrl9O5os"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>devops</category>
      <category>aws</category>
    </item>
    <item>
      <title>Day 3 - Create an AWS S3 Bucket Using Terraform</title>
      <dc:creator>ankitgadling</dc:creator>
      <pubDate>Wed, 26 Nov 2025 17:35:45 +0000</pubDate>
      <link>https://dev.to/ankitgadling/day-3-create-an-aws-s3-bucket-using-terraform-2dn8</link>
      <guid>https://dev.to/ankitgadling/day-3-create-an-aws-s3-bucket-using-terraform-2dn8</guid>
      <description>&lt;h2&gt;
  
  
  What is an S3 bucket?
&lt;/h2&gt;

&lt;p&gt;An Amazon S3 bucket is a scalable object storage container used to store files (objects) such as backups, logs, images, and static website assets. Each bucket has a globally unique name and can be configured with lifecycle policies, access controls, encryption, and versioning.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Durable object storage for static content, backups, and artifacts.&lt;/li&gt;
&lt;li&gt;Hosting static websites.&lt;/li&gt;
&lt;li&gt;Centralized storage for application logs or data.&lt;/li&gt;
&lt;li&gt;Remote Terraform state backends (when combined with locking).&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;AWS account and appropriate IAM credentials.&lt;/li&gt;
&lt;li&gt;AWS CLI configured (or environment variables AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY).&lt;/li&gt;
&lt;li&gt;Terraform installed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tips &amp;amp; best practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Bucket names must be globally unique - include a random suffix or org/project prefix.&lt;/li&gt;
&lt;li&gt;Enable encryption (SSE) and versioning for important data.&lt;/li&gt;
&lt;li&gt;Block public access unless intentionally hosting public assets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Create a VPC, S3 Bucket, and Implicit Dependency Using Terraform
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Install Terraform&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Download and install Terraform from the official website:&lt;br&gt;
&lt;a href="https://developer.hashicorp.com/terraform/downloads" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/downloads&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Configure AWS Credentials&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Install and configure AWS CLI:&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;Provide your:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Access Key&lt;/li&gt;
&lt;li&gt;AWS Secret Key&lt;/li&gt;
&lt;li&gt;AWS Region&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  * Output format
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Create &lt;code&gt;main.tf&lt;/code&gt; File&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Create a folder and inside it create a file named &lt;strong&gt;main.tf&lt;/strong&gt; with the following content:&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="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_vpc"&lt;/span&gt; &lt;span class="s2"&gt;"main"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;cidr_block&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;
  &lt;span class="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;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;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;"example-vpc"&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;"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;"example-bucket-${aws_vpc.main.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;"example-bucket"&lt;/span&gt;
    &lt;span class="nx"&gt;VPC&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Initialize Terraform and  Validate the Terraform Configuration&lt;/strong&gt;
&lt;/h3&gt;

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

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

&lt;/div&gt;



&lt;p&gt;This downloads the AWS provider and prepares the working directory.&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%2Fmsta3qoh8kppfy9mjjy8.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%2Fmsta3qoh8kppfy9mjjy8.png" alt="terraform init"&gt;&lt;/a&gt;&lt;br&gt;
Run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This checks for syntax or configuration errors.&lt;/p&gt;

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




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 5: Plan the Terraform Changes&lt;/strong&gt;
&lt;/h3&gt;

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

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

&lt;/div&gt;



&lt;p&gt;This shows what resources Terraform will 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%2F9n8zu9hzeqfn7vx4msux.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%2F9n8zu9hzeqfn7vx4msux.png" alt="terraform plan"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 6: Apply the Changes&lt;/strong&gt;
&lt;/h3&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Type &lt;strong&gt;yes&lt;/strong&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%2Fvt5qhi1v5gitlek0d22r.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%2Fvt5qhi1v5gitlek0d22r.png" alt="terraform apply"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Step 7: Destroy the Resources&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you are done, run:&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;Type &lt;strong&gt;yes&lt;/strong&gt; to confirm.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F155sqqzbc2p4zz7g9njg.png" alt="terraform destroy"&gt;
&lt;/h2&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/09HQ_R1P7Lw"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>devops</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day 2 - Terraform AWS Provider</title>
      <dc:creator>ankitgadling</dc:creator>
      <pubDate>Tue, 25 Nov 2025 16:23:42 +0000</pubDate>
      <link>https://dev.to/ankitgadling/day-2-terraform-aws-provider-36d8</link>
      <guid>https://dev.to/ankitgadling/day-2-terraform-aws-provider-36d8</guid>
      <description>&lt;h2&gt;
  
  
  What is a provider?
&lt;/h2&gt;

&lt;p&gt;A provider is a plugin that enables Terraform to manage resources from a specific cloud or service. It translates Terraform configuration (HCL) into API calls the provider understands. Providers are the bridge between Terraform and target platforms such as cloud providers, SaaS products, and other services.&lt;/p&gt;

&lt;p&gt;Providers can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Official (aws, gcp, azure, kubernetes)&lt;/li&gt;
&lt;li&gt;Partner&lt;/li&gt;
&lt;li&gt;Community&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Importance of versions
&lt;/h2&gt;

&lt;p&gt;Versioning matters. Terraform itself and providers evolve continuously new features, bug fixes, and breaking changes are common. Specifying and pinning provider and Terraform versions ensures consistent behavior across environments and prevents unexpected breakages. Use the terraform block's required_providers and required_version settings and rely on the provider lock file (terraform.lock.hcl) to maintain reproducible runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of the Terraform AWS Provider
&lt;/h2&gt;

&lt;p&gt;The Terraform AWS Provider allows Terraform to create, read, update, and delete AWS resources by converting HCL to AWS API requests. It covers a wide range of services (EC2, S3, VPC, IAM, RDS, Lambda, CloudWatch, and many more) and supports data sources, resource arguments, and lifecycle options.&lt;/p&gt;

&lt;p&gt;Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication: supports shared credentials (~/.aws/credentials), environment variables, profiles, STS assume role, EC2/ECS task roles, and SSO.&lt;/li&gt;
&lt;li&gt;Configuration: region, profile, access keys, assume_role, endpoints, and aliases for multiple providers/accounts/regions.&lt;/li&gt;
&lt;li&gt;Best practices: pin provider versions, use state locking/backends, split environments or accounts with workspaces or multiple providers, and test changes in non-production first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example (minimal):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;
            &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 4.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;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 1.0.0"&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-west-2"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/JFiMmaktnuM?si=GUeS8ZiaGEizCrxh" rel="noopener noreferrer"&gt;https://youtu.be/JFiMmaktnuM?si=GUeS8ZiaGEizCrxh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest" rel="noopener noreferrer"&gt;https://registry.terraform.io/providers/hashicorp/aws/latest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>30daysofawsterraform</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Day 1 - Introduction to Infrastructure as Code (IaC)</title>
      <dc:creator>ankitgadling</dc:creator>
      <pubDate>Mon, 24 Nov 2025 17:05:05 +0000</pubDate>
      <link>https://dev.to/ankitgadling/day-1-introduction-to-infrastructure-as-code-iac-29m4</link>
      <guid>https://dev.to/ankitgadling/day-1-introduction-to-infrastructure-as-code-iac-29m4</guid>
      <description>&lt;h2&gt;
  
  
  Why IaC is needed
&lt;/h2&gt;

&lt;p&gt;When you do big or repetitive tasks by hand, it’s easy to mess something up or forget a step. IaC helps by letting you write your infrastructure as code, so everything is repeatable, automated, and way less error-prone. Plus, it saves money because you can create resources only when you need them and delete them right after.&lt;br&gt;
Example: A developer can run a single command to build a temporary AWS environment for a demo, and remove it as soon as the demo ends so no charges keep adding up.&lt;/p&gt;


&lt;h2&gt;
  
  
  Common IaC Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Terraform (HashiCorp)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AWS CloudFormation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pulumi&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  What is Terraform?
&lt;/h2&gt;

&lt;p&gt;Terraform is an &lt;strong&gt;open-source Infrastructure as Code (IaC) tool&lt;/strong&gt; that allows you to define, preview, and apply infrastructure changes across many different cloud and on-prem providers. It lets teams manage resources using configuration files instead of manual steps.&lt;/p&gt;


&lt;h2&gt;
  
  
  HashiCorp Configuration Language (HCL)
&lt;/h2&gt;

&lt;p&gt;Terraform uses &lt;strong&gt;HCL&lt;/strong&gt;, a human-friendly configuration language that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Looks similar to JSON but has its own cleaner syntax&lt;/li&gt;
&lt;li&gt;Is designed to be easy to read and write&lt;/li&gt;
&lt;li&gt;Supports variables, modules, and expressions&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  How Terraform Works (High-Level Overview)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Write configuration files (&lt;code&gt;.tf&lt;/code&gt;)&lt;/strong&gt; to describe the infrastructure you want (e.g., VMs, networks, storage).&lt;/li&gt;
&lt;li&gt;Run &lt;strong&gt;&lt;code&gt;terraform init&lt;/code&gt;&lt;/strong&gt;
Initializes the working directory, downloads required providers and modules.&lt;/li&gt;
&lt;li&gt;Run &lt;strong&gt;&lt;code&gt;terraform plan&lt;/code&gt;&lt;/strong&gt;
Shows the changes Terraform will perform creating, modifying, or deleting resources.&lt;/li&gt;
&lt;li&gt;Run &lt;strong&gt;&lt;code&gt;terraform apply&lt;/code&gt;&lt;/strong&gt;
Executes the plan, provisioning or updating resources and saving the state.&lt;/li&gt;
&lt;li&gt;Run &lt;strong&gt;&lt;code&gt;terraform destroy&lt;/code&gt;&lt;/strong&gt;
Cleans up and removes the infrastructure when it’s no longer needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Terraform communicates with cloud platforms through &lt;strong&gt;providers&lt;/strong&gt;, which handle API calls and ensure resources are created, updated, or deleted in the correct order based on dependencies.&lt;/p&gt;



&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/s5fwSG_00P8"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>infrastructureascode</category>
      <category>30daysofawsterraform</category>
    </item>
    <item>
      <title>Why I Switched to Conventional Commits (and Why You Should Too)</title>
      <dc:creator>ankitgadling</dc:creator>
      <pubDate>Fri, 08 Aug 2025 08:50:50 +0000</pubDate>
      <link>https://dev.to/ankitgadling/why-i-switched-to-conventional-commits-and-why-you-should-too-3i69</link>
      <guid>https://dev.to/ankitgadling/why-i-switched-to-conventional-commits-and-why-you-should-too-3i69</guid>
      <description>&lt;p&gt;Hello Buddy,&lt;/p&gt;

&lt;p&gt;This is Ankit, a Python developer currently floating in the AWS cloud.&lt;/p&gt;

&lt;p&gt;When I started writing code, I was always stuck when it came to committing. I had no idea what to write in a commit message, which often resulted in me not committing any code for a long time. Eventually, when it was time to push, I would end up with so many lines and files changed all dumped into one ugly commit.&lt;/p&gt;

&lt;p&gt;I kept doing this for a long time.&lt;/p&gt;

&lt;p&gt;Then I realized my mistake and started committing code based on a feature or fix, This small change helped me understand my code better and work in a more structured way.&lt;/p&gt;

&lt;p&gt;However, I still wasn't following any pattern when writing commit messages. This made my project’s commit history look weird and inconsistent.&lt;/p&gt;

&lt;p&gt;While exploring some open-source code, I noticed certain patterns in commit messages. That's when I discovered Conventional Commits as one of the best and most effective ways of writing commit messages.&lt;/p&gt;

&lt;p&gt;Now, I use it every day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My old commit style (bad examples):&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;update
fix bug
done some changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;My new commit style (Conventional Commits examples):&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;feat(auth): add support for Google login
fix(api): handle empty payload in POST requests
refactor(db): improve query performance for user search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Conventional Commits Helped Me&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear history - I can look at git log and instantly understand what each commit does.&lt;/li&gt;
&lt;li&gt;Better collaboration - Team members know exactly what changed and why.&lt;/li&gt;
&lt;li&gt;Automation - Tools can automatically generate changelogs or trigger CI/CD steps based on commit types.&lt;/li&gt;
&lt;li&gt;Discipline - It forces me to break work into smaller, meaningful chunks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you often find yourself with one massive commit and a vague message, try adopting &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Start small: pick one convention (feat, fix, docs, etc.) and stick with it. Over time, you’ll see your commit history become cleaner, more meaningful, and far easier to work with for both you and your team.&lt;/p&gt;

</description>
      <category>git</category>
      <category>commit</category>
      <category>programming</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
