Terraform configuration ยท 10 min read

Terraform count vs for_each explained

count and for_each both repeat resources. count is useful for simple numbered copies. for_each is normally safer when each instance has a meaningful stable key such as api, worker, or admin.

for_each with stable service names

Each map key becomes part of the Terraform resource address, making the api and worker instances easier to identify and change safely.

resource "aws_instance" "service" {
  for_each = { api = "t3.micro", worker = "t3.small" }

  instance_type = each.value
  tags = { Name = each.key }
}

Terraform tracks addresses, not intentions

A count resource is addressed by index, such as aws_instance.web[0]. A for_each resource is addressed by a key, such as aws_instance.service["api"]. Terraform uses these addresses to decide which real object each configuration block represents.

If an index changes meaning, Terraform can treat one object as removed and another as new. Stable names make planned changes clearer and reduce accidental replacement risk.

Choose the right collection

Maps pair a stable key with a value. In the example, each.key supplies the service name and each.value supplies the instance size. Sets work when the key itself is all you need.

Choose readable, persistent keys. Avoid generating them from volatile details that could make Terraform believe an existing resource is a different object.

Changing an existing pattern

Moving from count to for_each changes resource addresses. In a production environment, plan the migration and use moved blocks or state migration guidance so Terraform understands that the real resource should keep its identity.

For learners, the key question is simple: is this resource merely copy number two, or is it a distinct role that deserves a stable name?

Put it into practice

Create api and worker with for_each, then add admin. Compare the predictable address change with inserting a value at the front of a count-based list.

  1. Use count for a genuine numeric quantity.
  2. Use for_each for named items in a map or set.
  3. Use count.index only inside a count resource.
  4. Use each.key and each.value only inside a for_each resource.