By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
count
for_each
You’re deploying 10 identical EC2 instances for a web app tier. Or 50 IAM users with the same permissions. Or 3 S3 buckets with slightly different names but identical policies.
Do you: - Copy-paste the same resource block 10 times? (No. That’s a maintenance nightmare.) - Use a shell script to loop and call terraform apply in a loop? (No. That breaks Terraform’s state tracking.) - Use count or for_each? (Yes. This is the only way to dynamically create multiple instances of a resource while keeping Terraform’s state clean.)
terraform apply
aws_instance.web[0]
aws_instance.web[1]
count = 5
count = 10
aws_instance.web[3]
apply
Real-world scenario:You’re migrating a legacy app to AWS. The app needs 3 identical web servers, 2 app servers, and 1 database. Instead of writing 6 separate aws_instance blocks, you use count or for_each to define them once, then let Terraform handle the rest.
aws_instance
hcl resource "aws_instance" "web" { count = 3 # Creates 3 instances: web[0], web[1], web[2] ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" }
count = 3
count = 2
web[2]
web[1]
web[0]
hcl resource "aws_iam_user" "developers" { for_each = toset(["alice", "bob", "charlie"]) # Creates 3 users: alice, bob, charlie name = each.key }
"bob"
bob
Works with maps (key-value pairs): ```hcl variable "users" { type = map(object({ role = string })) default = { alice = { role = "admin" } bob = { role = "dev" } } }
resource "aws_iam_user" "example" { for_each = var.users name = each.key tags = { Role = each.value.role } } ```
toset()
tomap()
hcl for_each = toset(["a", "b", "c"]) # Converts list to set
each.key
each.value
hcl resource "aws_s3_bucket" "example" { for_each = { logs = "us-east-1" backups = "us-west-2" } bucket = "my-bucket-${each.key}" region = each.value }
bucket = "app-${each.key}"
region = each.value
count.index
hcl resource "aws_instance" "web" { count = 3 ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" tags = { Name = "web-${count.index}" } }
terraform --version
aws sts get-caller-identity
Initialize a new Terraform project: bash mkdir tf-count-demo && cd tf-count-demo touch main.tf
bash mkdir tf-count-demo && cd tf-count-demo touch main.tf
Define the aws_instance resource with count: ```hcl provider "aws" { region = "us-east-1" }
resource "aws_instance" "web" { count = 3 # Creates 3 instances ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 (us-east-1) instance_type = "t2.micro" tags = { Name = "web-${count.index}" } } ```
Apply the configuration: bash terraform init terraform plan terraform apply -auto-approve
bash terraform init terraform plan terraform apply -auto-approve
Verify the instances: bash aws ec2 describe-instances --filters "Name=tag:Name,Values=web-*" --query "Reservations[*].Instances[*].[InstanceId,Tags[?Key=='Name'].Value|[0]]" --output table Expected output: ```
bash aws ec2 describe-instances --filters "Name=tag:Name,Values=web-*" --query "Reservations[*].Instances[*].[InstanceId,Tags[?Key=='Name'].Value|[0]]" --output table
| DescribeInstances | +--------------+-----------------------+ | i-012345678 | web-0 | | i-876543210 | web-1 | | i-123456789 | web-2 | +--------------+-----------------------+ ```
bash terraform destroy -auto-approve
main.tf
variable "users" { type = map(object({ role = string })) default = { alice = { role = "admin" } bob = { role = "dev" } charlie = { role = "read-only" } } }
Apply the configuration: bash terraform apply -auto-approve
bash terraform apply -auto-approve
Verify the users: bash aws iam list-users --query "Users[].UserName" --output table Expected output: ```
bash aws iam list-users --query "Users[].UserName" --output table
| ListUsers | +-------------------+ | alice | | bob | | charlie | +-------------------+ ```
sensitive = true
hcl variable "db_password" { type = string sensitive = true }
hcl resource "aws_iam_user_policy_attachment" "example" { for_each = aws_iam_user.example user = each.key policy_arn = "arn:aws:iam::aws:policy/${each.value.role}" }
hcl resource "aws_instance" "web" { count = 3 tags = { Name = "web-${count.index}" Environment = "prod" Terraform = "true" } }
aws_instance.web[2]
aws_db_instance.main
terraform plan
Invalid for_each argument: value must be a map or set of strings
web-1
web-0
❌ for_each (overkill for identical resources).
"You need to create IAM users with different permissions. Which meta-argument is best?"
❌ count (risky if users are removed).
"What happens if you change count = 3 to count = 2?"
❌ Terraform destroys the first instance (web[0]).
"How do you reference the current item in for_each?"
Deploy 3 S3 buckets with the following names: - my-app-logs-us-east-1 - my-app-backups-us-west-2 - my-app-assets-eu-west-1
my-app-logs-us-east-1
my-app-backups-us-west-2
my-app-assets-eu-west-1
Use for_each and a map of regions.
provider "aws" { region = "us-east-1" } variable "buckets" { type = map(string) default = { logs = "us-east-1" backups = "us-west-2" assets = "eu-west-1" } } resource "aws_s3_bucket" "example" { for_each = var.buckets bucket = "my-app-${each.key}-${each.value}" region = each.value }
buckets
logs
backups
assets
us-east-1
us-west-2
eu-west-1
count = N
for_each = toset(["a", "b"])
for_each = toset(["alice", "bob"])
for_each = { key = "value" }
for_each = { logs = "us-east-1" }
name = each.key
name = "web-${count.index}"
sensitive
variable "password" { sensitive = true }
count and for_each are the difference between "I’ll just copy-paste this 50 times" and "I’ll let Terraform handle it."
Now go deploy something! ?
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.