Learn · Modules and iteration
count against for_each, and the index shift
Removing the second of five instances destroys three of them. Not because anything is broken — because count keys are positions.
Positions against names
count gives each instance a number: web[0], web[1], web[2]. for_each gives each one a key from the collection: web["alpha"], web["beta"]. Both produce the same resources, and the difference is what happens when the collection changes.
A number is a position. Take the middle entry out of a list of three and everything after it moves down one — so web[1] now refers to what used to be web[2], and the plan compares the wrong pairs. A key is a name, and taking one out takes out exactly one.
The catastrophe, in one edit
Three workers, count = length(var.names), names ["alpha", "beta", "gamma"]. Remove beta. The list is now two long, so web[2] is destroyed — which is correct — and web[1], which held beta, is now compared against gamma and replaced.
Two resources destroyed, one of them for no reason anybody intended, from deleting one line. With five instances and one removed from the middle, it is three.
Before you run it
A count-based resource has five instances. You remove the second entry from the list it counts. How many are destroyed or replaced?
The fix, and what it costs
for_each = toset([...]) keys the instances by their own values, so removing one removes one. That is the fix, and it is almost always the right default.
Switching an existing resource from count to for_each is itself the catastrophe, though: every key changes, so every instance is destroyed and recreated. moved blocks are what make that migration free — one per instance, saying web[0] is now web["alpha"], and the plan comes out empty.
- for_each = toset(["a", "b", "c"])+ for_each = toset(["a", "c"])
Watch: Exactly one subnet destroyed — and what that does to the workers sitting in the others.
aws_subnet.cidr_block — Why the blast radius is what it is: a subnet cannot be re-addressed, so every instance the shift touches is rebuilt rather than updated.
The plan
The same service every claim above was made about. Nothing here is graded — load whatever you like, or change nothing and read what the configuration already produces.
Plan: 0 to add, 0 to change, 0 to destroy.
Nothing in this plan is destroyed.