count, for_each, and Identity

Scenario: Deleting the first item from a counted list makes Terraform propose updates or replacements for every later instance.

count indexes instances numerically and suits truly interchangeable repetitions or optional singletons. for_each keys instances by stable strings and suits named objects. The key becomes part of the state address, so choose durable business identity—not a mutable display label. Convert lists to sets only when order and duplicates are intentionally irrelevant. Dynamic blocks repeat nested blocks; they do not replace resource-level for_each.

Analogy: Numbered coat hooks work until someone removes hook zero and every coat shifts. Named lockers preserve ownership when the roster changes.

A worked configuration

variable "servers" { type = map(object({ size = string })) }
resource "fakecloud_server" "node" {
  for_each = var.servers
  name     = each.key
  size     = each.value.size
}

Before changing from count to for_each, map old addresses to new ones with moved blocks or explicit state moves. Otherwise a clean refactor can replace an entire fleet.

Note: Treat the plan as a change contract: understand every create, update, replacement, and destroy before approving it.
Goal: Reinforce this lesson in the tf-count-for-each Terraform lab. Open /labs/terraform and choose slug tf-count-for-each; the lab runs real Terraform against the offline FakeCloud provider.