Repetition is everywhere, and choosing count where for_each belongs causes destructive plans later.
Two meta-arguments create multiple instances from one block:
- count:
count = 3makesaws_instance.web[0],[1],[2], withcount.indexinside. Also the standard way to make a resource conditional:count = var.enabled ? 1 : 0. - for_each: takes a map or a set of strings and makes one instance per key:
aws_iam_user.u["ana"], witheach.keyandeach.valueinside.
Why it matters: instances are tracked by index (count) or key (for_each). With count over a list ["a", "b", "c"], removing "a" shifts "b" to index 0 and "c" to 1, so Terraform plans to change or replace b and c and destroy the last one. With for_each, removing "a" destroys only "a". Rule of thumb: use count for N identical things or on/off switches; use for_each whenever items have identities.
for_each keys must be known at plan time: you can't key on an attribute generated during apply, such as an ID. Use names from your input. Convert a list with toset(var.names), or a list of objects with { for o in var.items : o.name => o }.
Refer to all instances with splat (aws_instance.web[*].id, count only) or a for expression ([for u in aws_iam_user.u : u.arn], works for both). Both meta-arguments also work on module blocks.
Example
variable "users" {
type = set(string)
default = ["ana", "bo", "cy"]
}
variable "create_bastion" {
type = bool
default = false
}
resource "terraform_data" "user" {
for_each = var.users # address: terraform_data.user["bo"]
input = "user-${each.key}"
}
resource "terraform_data" "bastion" {
count = var.create_bastion ? 1 : 0 # conditional resource
input = "bastion"
}
output "user_inputs" { value = [for u in terraform_data.user : u.output] }
# ["user-ana", "user-bo", "user-cy"]
# Removing "ana" later destroys only terraform_data.user["ana"].Remember
- count: N copies or on/off; for_each: one instance per key
- Removing a list item under count shifts indexes and churns resources
- for_each keys must be known at plan time
Watch out for
- Using count over a list of names, then deleting the first name and watching every later instance be replaced.