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/terraformand choose slugtf-count-for-each; the lab runs real Terraform against the offline FakeCloud provider.