patternbashterraformMajor
count vs for_each: choose for_each for resources that have a meaningful identity key
Viewed 0 times
countfor_eachindex shiftingstable addresstosetiterationmeta-argument
Error Messages
Problem
Using
count to create multiple similar resources (e.g., 3 subnets) assigns state addresses by index (aws_subnet.this[0], aws_subnet.this[1]). Removing an element from the middle of the list renumbers all subsequent resources, causing Terraform to destroy and recreate them unnecessarily.Solution
Use
for_each with a map or set when the resources have stable identity keys. This gives each resource a stable state address based on its key, so adding or removing one resource does not affect the others.# Fragile with count: removing "us-east-1a" renumbers [1] to [0]
variable "azs" {
default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}
resource "aws_subnet" "bad" {
count = length(var.azs)
availability_zone = var.azs[count.index]
}
# Stable with for_each
variable "subnet_config" {
default = {
"us-east-1a" = "10.0.1.0/24"
"us-east-1b" = "10.0.2.0/24"
"us-east-1c" = "10.0.3.0/24"
}
}
resource "aws_subnet" "good" {
for_each = var.subnet_config
availability_zone = each.key
cidr_block = each.value
}Why
With
count, the state address is an index. When you remove an element, all higher indices shift down, causing Terraform to see those resources as changed even though only one was removed. for_each uses the map key as the address, which is stable.Gotchas
- for_each requires a map or set — convert lists with
toset()when keys don't matter - for_each keys must be known at plan time — dynamic values from resources (not data sources) cause plan errors
- count is still appropriate for truly interchangeable replicas (e.g., identical worker nodes)
- Mixing count and for_each on the same resource is not allowed
Context
Creating multiple similar resources from a list or map of configurations
Revisions (0)
No revisions yet.