for_each meta-argument — the recommended way to create multiple resources when instance identity and lifecycle stability matter. Unlike count, for_each ties each resource instance to a meaningful key, which prevents index-shifting and makes changes safer and more predictable for production workloads.

for_each? When resources are keyed by meaningful identifiers (names, subnet IDs, DNS names, etc.), Terraform can track each resource independently. This prevents accidental destruction and recreation caused by reordering or changing collections that are tracked only by numeric indexes.

variable.resource_groupsis declared asset(string): a collection of unique values without a guaranteed order.for_each = var.resource_groupscreates one resource instance per element in the set.- When iterating a set, both
each.keyandeach.valuerefer to the element value (e.g.,"rg-dev"and"rg-prod"). When iterating a map,each.keyis the map key andeach.valueis the map value.
for_each uses meaningful keys rather than numeric indexes, Terraform state does not shift when you add or remove other items. This makes for_each far safer than count in many production scenarios.
Prefer
for_each when each resource has a meaningful identifier (name, subnet ID, DNS name, etc.). Use count only for N identical resources where individual identity or lifecycle does not matter.count is brittle
With count, Terraform identifies resources by their numeric index (0, 1, 2, …). Reordering or removing elements can change those indexes and cause Terraform to destroy and recreate resources unnecessarily.
count-style example (index-based):
for_each to avoid index shifting
for_each results:
- A resource using
for_eachbecomes a map keyed by the iteration key. Reference an instance withazurerm_resource_group.rg["0"].name. - Avoid mixing index-based references (e.g.,
rg[0]) with map-style lookups fromfor_each. Use map-style lookups consistently.
for_each vs count
Typical local workflow
for_each instance
- Using
terraform destroy --target 'azurerm_resource_group.rg["0"]'orterraform apply -target=...is possible but generally discouraged for routine operations. Terraform will warn you when targeting because the plan may not represent all configuration changes.
-target (abridged):
Avoid relying on
-target for normal workflows. Targeting can produce incomplete or unsafe plans when resources have dependencies, and may cause unintended changes.for_each
- Update the collection used by
for_eachto remove the key you want to delete. - Run
terraform planandterraform apply. Terraform will plan and destroy only the resource whose key was removed and leave other keyed instances intact.
"1"
Before:
"1"):
- Use
for_eachwhen instances have meaningful identities (names, subnet IDs, DNS records, etc.). It maps instances to stable keys and prevents index-driven recreation. - Use
countonly when you truly need N indistinguishable, ordinal resources. - Reference
for_eachinstances withresource.name["key"], and avoid mixing indexing styles. - To remove a single instance, remove its key from the
for_eachcollection andapplythe change. Avoid-targetunless you fully understand the dependency implications.
- Terraform: Meta-arguments — for_each and count
- Terraform: Expressions — each object
- Azure Provider (azurerm) Documentation