Skip to main content
In this lesson you’ll learn how to use Terraform’s for_each meta-argument to create multiple, uniquely configured resources from a single resource block. for_each is a more flexible alternative to count when you need per-resource uniqueness rather than many identical instances. Why use for_each (versus count)
  • for_each iterates over a map or set, allowing unique configuration per instance.
  • Each instance receives a stable key (the map key or set element) instead of an index. This stability reduces accidental recreation of unrelated resources when items are added or removed.
  • Use for_each when resources need different names, sizes, tags, networks, or other unique attributes.
  • Inside the resource block you can reference each.key and each.value to access the current item.
Example: map of VM names to sizes
variable "vms" {
  type    = map(string)
  default = {
    "vm1" = "Standard_D2s_v3"
    "vm2" = "Standard_D4s_v3"
    "vm3" = "Standard_B2ms"
  }
}

resource "azurerm_virtual_machine" "example" {
  for_each            = var.vms
  name                = each.key
  location            = "East US"
  resource_group_name = "my-resource-group"
  vm_size             = each.value

  os_profile {
    computer_name  = each.key
    admin_username = "adminuser"
  }

  # Additional required blocks (networking, storage, etc.) omitted for brevity.
}
Because var.vms contains three key/value pairs, Terraform creates three VMs: vm1, vm2, and vm3, each with its configured size. Referencing resources created with for_each
  • Address an individual instance by its key in square brackets:
    • azurerm_virtual_machine.example["vm1"]
    • azurerm_virtual_machine.example["vm2"]
    • azurerm_virtual_machine.example["vm3"]
  • Use these keyed references when wiring resources together (for example, passing an instance ID or IP to another resource).
Using each.key and each.value inside the block
  • each.key is the map key (here, the VM name).
  • each.value is the map value (here, the VM size).
  • You can reference each.key/each.value multiple times to configure name, tags, hostnames, and more.
  • Combine them in interpolations. For example, to add a suffix to the computer name:
os_profile {
  computer_name  = "${each.key}-web"
  admin_username = "adminuser"
}
Use cases and recommendations
  • Prefer for_each when instances require distinct attributes or when you want stable addressing that won’t shift as you add or remove items.
  • count is still useful when creating many identical resources where uniqueness is not needed.
  • Map values can be primitive (strings, numbers) or nested objects to carry richer per-resource configuration (regions, tags, disk sizes, network IDs, etc.).
Comparison: for_each vs count
Featurefor_eachcount
Iterates overmap or setinteger range
Stable addressingYes — keyed by map/set element (each.key)No — indexed by position (0..n-1)
Best forResources with unique attributesRepeated identical resources
Examplefor_each = var.vmscount = var.instance_count
Prefer for_each when your instances have unique attributes or when you want stable instance addressing that won’t shift as items are added or removed.
When converting existing resources from count to for_each (or vice versa), resource addresses change. This can cause Terraform to plan to recreate resources unless you import or manipulate state appropriately. Always review the plan and consider state migration steps.
Links and references That covers the for_each meta-argument and how it compares to count. Use for_each to keep your configuration DRY while enabling per-resource uniqueness and stable addressing.

Watch Video

Practice Lab