# 📘 Terraform Series – Day 9

Meta Arguments: `count` vs `for_each` with Output

### 📝 Abstract

In Terraform, managing multiple resources efficiently is a common requirement in real-world DevOps projects. While creating multiple instances may seem straightforward, choosing the right approach can significantly impact scalability, flexibility, and maintainability.

This blog explores **Terraform meta arguments**, specifically `count` and `for_each`, and demonstrates how they behave differently when creating multiple resources. It also covers how outputs change based on these approaches and when to use `depends_on` for explicit dependencies.

### 🎯 Objectives

After completing this blog, you will be able to:

*   Understand what **meta arguments** are in Terraform
    
*   Create multiple resources using `count`
    
*   Identify limitations of `count`
    
*   Use `for_each` for better flexibility
    
*   Handle outputs correctly for both approaches
    
*   Understand the use of `depends_on`
    

### 🔷 Step 1: Understanding Meta Arguments

Meta arguments are **special Terraform keywords** that control resource behavior.

Common Meta Arguments:

*   `count`
    
*   `for_each`
    
*   `depends_on`
    
*   `lifecycle`
    

👉 In this tutorial, we focus on:

*   `count`
    
*   `for_each`
    

### 🔷 Step 2: Creating Multiple Resources using `count`

✅ Code

```shell
resource "aws_instance" "my_instance" {
  count         = 2
  ami           = var.ec2_ami_id
  instance_type = var.ec2_instance_type
}
```

![](https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/4d8c6f34-136b-4c8f-a902-f63b594b0c8a.png align="center")

### 🔍 Explanation

*   Terraform creates **2 EC2 instances**
    
*   Indexed as:
    

```shell
aws_instance.my_instance[0]
aws_instance.my_instance[1]
```

### 🔷 Step 3: Output using `count`

```shell
output "ec2_public_ip" {
  value = aws_instance.my_instance[*].public_ip
}
```

![](https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/02777522-98d0-45cd-b23c-69ff5f4270d6.png align="center")

![](https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/1cee2ab4-6b35-4159-84ee-ebcdb04ecc9c.png align="center")

### 🧠 Concept

*   `[*]` → **Splat Expression**
    
*   Used to extract values from multiple resources
    

### 🔷 Step 4: Limitation of `count`

Using `count` has restrictions:

*   Same configuration for all instances
    
*   Cannot assign:
    
    *   Different names ❌
        
    *   Different instance types ❌
        

### 🔷 Step 6: Using `for_each` (Better Approach)

```shell
resource "aws_instance" "my_instance" {
  for_each = {
    Apurv-1 = "t2.micro"
    Apurv-2 = "t2.medium"
  }

  ami           = var.ec2_ami_id
  instance_type = each.value

  tags = {
    Name = each.key
  }
}
```

### 🧠 Explanation

*   `each.key` → Instance Name
    
*   `each.value` → Instance Type
    

👉 Each instance becomes **unique and configurable**

### 🔷 apply terraform and check output

```shell
terraform apply 
```

![](https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/73642d3d-e784-43be-b50d-c0960014e775.png align="center")

### 🔷 Step 7: Why Old Output Fails

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">In the above outputs, we get a list of Public IPs and DNS values. However, the issue is that Terraform only returns a <strong>list of values</strong>, and it does not clearly indicate which IP belongs to which instance.</div>
</div>

❌ Old Code

```shell
aws_instance.my_instance[*].public_ip
```

### ❗ Reason

*   `count` → returns **list**
    
*   `for_each` → returns **map**
    

👉 So `[*]` does not work here

### 🔷 Step 8: Correct Output with `for_each`

✅ Public IP

```shell
output "ec2_public_ip" {
  value = [
    for instance in aws_instance.my_instance :
    instance.public_ip
  ]
}
```

✅ Public DNS

```shell
output "ec2_public_dns" {
  value = [
    for instance in aws_instance.my_instance :
    instance.public_dns
  ]
}
```

✅ Private IP

```shell
output "ec2_private_ip" {
  value = [
    for instance in aws_instance.my_instance :
    instance.private_ip
  ]
}
```

![](https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/ce86207e-05e3-434a-a192-f81427ef383a.png align="center")

### 🔷 Step 9: Final Result

After applying `for_each`:

*   Different instance names ✅
    
*   Different instance types ✅
    
*   Correct outputs fetched ✅
    

![](https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/a2fbe1b6-a303-4db8-9277-9d58670ec226.png align="center")

### 🔷 Step 10: Understanding `depends_on`

✅ Definition

`depends_on` is used to **explicitly define dependencies**

⚙️ Example

```shell
depends_on = [
  aws_security_group.my_groups,
  aws_key_pair.my_key
]
```

![](https://cdn.hashnode.com/uploads/covers/685cdc0d5ca95e55fac3ab09/827a91ae-6586-416e-ab82-20d6b4af4997.png align="center")

### 🧠 When to Use

*   When Terraform **cannot detect dependency automatically**
    
*   When using **hardcoded values**
    
*   When dependencies are **indirect**
    

❌ When NOT to Use

```shell
key_name = aws_key_pair.my_key.key_name
```

👉 Terraform automatically handles this (**implicit dependency**)

### 🚀 Conclusion

*   Use `count` → for simple, identical resources
    
*   Use `for_each` → for flexible and scalable setups
    
*   Understand difference between **list vs map outputs**
    
*   Use `depends_on` only when required
    

### **👨‍💻 About the Author**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1751797710818/123a7231-3dca-4273-ad68-7bd026f69b95.png?auto=compress,format&format=webp&auto=compress,format&format=webp&auto=compress,format&format=webp&auto=compress,format&format=webp&auto=compress,format&format=webp align="center")

“A complete Terraform series covering everything from fundamentals to advanced real-world infrastructure automation in a DevOps environment.”

### **📬 Let's Stay Connected**

*   📧 **Email**: [**gujjarapurv181@gmail.com**](mailto:gujjarapurv181@gmail.com)
    
*   🐙 **GitHub**: [**github.com/ApurvGujjar07**](http://github.com/ApurvGujjar07)
    
*   💼 **LinkedIn**: [**linkedin.com/in/apurv-gujjar**](http://linkedin.com/in/apurv-gujjar)
