for_each meta-argument is a flexible alternative to count when you need to create multiple resources that are not identical. Unlike count, which iterates a numeric index, for_each iterates over a map or a set of strings. Each instance created by for_each is identified by a stable key (the map key or set element), which helps prevent accidental resource replacement when items are added or removed.
Use for_each when you want:
- Unique names, sizes, tags, or other attributes per resource.
- Stable identities so Terraform can track each instance reliably across changes.
Prefer
for_each when resources are unique or require stable identities. count is still useful for N identical resources, but for_each reduces accidental replacements when items are added or removed.for_each to create one VM per map entry. Inside the resource block you can reference the map key with each.key and the value with each.value.
- Use the map-keyed resource address:
azurerm_virtual_machine.example["vm1"] - Or reference attributes:
azurerm_virtual_machine.example["vm1"].id
- You can combine
each.keyin strings:
for_eachaccepts:- a map (
map(string)etc.) —each.keyis the map key andeach.valueis the corresponding value. - a set of strings — each instance key is the set element and
each.valueequals that element.
- a map (
- If you have a list, convert it to a set to remove ordering and duplicates:
for_each = toset(var.my_list) - If you need unique keys from a list, turn it into a map using
zipmapor another transformation, for example:Herevar.namesbecomes the keys andvar.sizesthe values.
for_each vs count
Changing the keys used by
for_each (for example renaming map keys) is a breaking change: Terraform treats the new key as a new resource and will destroy the old resource. Rename resources deliberately and consider lifecycle or terraform state commands for complex migrations.- Use meaningful map keys (like names or unique IDs). These keys are the stable identifiers Terraform uses to track instances.
- Prefer maps when you need different attributes per instance; use sets for simple lists of unique names.
- For large numbers of identical resources where identity isn’t important,
countmay be more concise. - When converting lists, remember
toset()removes ordering — use it when ordering is irrelevant. - Use explicit
depends_onorlifecycleblocks sparingly; stable keys usually reduce the need for complex lifecycle rules.
- Terraform documentation: https://www.terraform.io/docs/language/meta-arguments/for_each.html
- Transformations:
toset(),zipmap(), and other builtin functions — see the Functions reference in Terraform docs.