Provisioning Multiple AWS EC2 Instances Using Terraform: for_each vs count

Infrastructure as Code (IaC) is a core skill for any DevOps engineer, and Terraform is one of the most widely used tools for this purpose.
In this article, I’ll walk through two practical ways to create multiple EC2 instances in AWS using Terraform:
Using
for_eachfor environment-based instancesUsing
countfor creating identical instances
This blog is based on my hands-on Terraform real execution results
Why Multiple Instances with Terraform?
In real-world environments, we often need:
Different EC2 instances for dev, qa, prod
Or multiple identical instances for scaling or testing
Terraform provides two powerful meta-arguments to achieve this:
for_eachcount
Let’s understand both with hands-on examples.
Approach 1: Creating Environment-Based EC2 Instances Using for_each
Objective
Create EC2 instances for different environments (dev, qa, prod) with different instance types using a single Terraform configuration.
Terraform Folder Structure
.
├── main.tf
├── variables.tf
├── outputs.tf
variables.tf
variable "env_instances" {
description = "Map of environments and their instance types"
type = map(string)
default = {
dev = "t2.micro"
qa = "t2.small"
prod = "t2.medium"
}
}
variable "ami_id" {
description = "AMI ID to use for all instances"
type = string
default = "ami-0c02fb55956c7d316"
}
variable "region" {
description = "AWS region"
type = string
default = "us-east-1"
}
Why map?
Each environment acts as a key, making resource management more readable and predictable.
main.tf
provider "aws" {
region = var.region
}
resource "aws_instance" "env_instances" {
for_each = var.env_instances
ami = var.ami_id
instance_type = each.value
tags = {
Name = "${each.key}-instance"
Environment = each.key
}
}
Key Insight
each.key→ environment name (dev / qa / prod)each.value→ instance type
outputs.tf
output "instance_ids" {
value = { for k, v in aws_instance.env_instances : k => v.id }
}
output "instance_public_ips" {
value = { for k, v in aws_instance.env_instances : k => v.public_ip }
}
Execution Steps
terraform init
terraform plan
terraform apply
After applying, Terraform creates three EC2 instances, each mapped to its environment.
Expected Output
| Environment | Instance Name | Instance Type |
| dev | dev-instance | t2.micro |
| qa | qa-instance | t2.small |
| prod | prod-instance | t2.medium |
AWS Console confirms all instances are running successfully
Approach 2: Creating Identical EC2 Instances Using count
Objective
Create multiple identical EC2 instances using Terraform count.
variables.tf
variable "instance_count" {
description = "Number of identical EC2 instances"
default = 3
}
variable "instance_type" {
default = "t2.micro"
}
variable "ami_id" {
default = "ami-0f9708d1cd2cfee41"
}
variable "availability_zone" {
default = "ap-south-1a"
}
main.tf
resource "aws_instance" "count_instances" {
count = var.instance_count
ami = var.ami_id
instance_type = var.instance_type
availability_zone = var.availability_zone
tags = {
Name = "count-instance-${count.index + 1}"
}
}
How count works
count.indexstarts from0Useful when resources are identical
outputs.tf
output "instance_ids" {
value = [for i in aws_instance.count_instances : i.id]
}
output "instance_public_ips" {
value = [for i in aws_instance.count_instances : i.public_ip]
}
Execution Steps
terraform init
terraform plan
terraform apply
Expected Output
| Instance Name | Instance Type | AZ |
| count-instance-1 | t2.micro | ap-south-1a |
| count-instance-2 | t2.micro | ap-south-1a |
| count-instance-3 | t2.micro | ap-south-1a |
Verified successfully in AWS EC2 Console
for_each vs count – When to Use What?
| Feature | for_each | count |
| Resource identity | Key-based | Index-based |
| Best for | Env-based, unique configs | Identical resources |
| Readability | High | Moderate |
| Deleting one item | Safe | Risky (index shift) |
Final Thoughts
Use for_each when:
Environments differ (dev / qa / prod)
You want safer, more readable infrastructure
Use count when:
Resources are identical
You only care about quantity
Both approaches are essential for real-world Terraform usage, and mastering them makes your IaC clean, scalable, and production-ready.



