Skip to main content
The Terraform 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.
Example: define a variable that is a map of VM names to VM sizes, then use 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.
Referencing created instances
  • Use the map-keyed resource address: azurerm_virtual_machine.example["vm1"]
  • Or reference attributes: azurerm_virtual_machine.example["vm1"].id
Interpolation examples
  • You can combine each.key in strings:
Types and conversions
  • for_each accepts:
    • a map (map(string) etc.) — each.key is the map key and each.value is the corresponding value.
    • a set of strings — each instance key is the set element and each.value equals that element.
  • 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 zipmap or another transformation, for example:
    Here var.names becomes the keys and var.sizes the values.
Comparison: 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.
Best practices and tips
  • 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, count may be more concise.
  • When converting lists, remember toset() removes ordering — use it when ordering is irrelevant.
  • Use explicit depends_on or lifecycle blocks sparingly; stable keys usually reduce the need for complex lifecycle rules.
References and further reading

Watch Video

Practice Lab