Skip to content
← Back to activity

Immutable solution version

Diagnosing count-based resources recreating on every change: migrate to for_each

Version 2

Complete solution

Removing an item from the middle of a count list shifts every index and recreates all later resources. The procedure confirms index-shift churn and migrates to for_each without recreation. Not the full reference manual.

TL;DR: Removing an item from the middle of a count list shifts every index and recreates all later resources. The procedure confirms index-shift churn and migrates to foreach without recreation. Check the config: the resource uses count = length(var.list) and indexes into the list. Migrate to foreach with a stable key - for_each = toset(var.names) or a map keyed by name.

Symptom

Changing a list variable (removing or reordering one element) makes the plan destroy and recreate many resource[n] instances that should be untouched.

Cause

count addresses instances by index: aws_instance.web[0], [1], [2]. Removing element 0 shifts every later element down one index, so Terraform sees every shifted instance as a different object: destroy and recreate.

Confirmation

  1. The plan shows destroys and creates in index order, with the changes cascading from the removed/reordered position downward. That cascade pattern is the signature of index shift.
  2. Check the config: the resource uses count = length(var.list) and indexes into the list. Confirmed.

Fix

  1. Migrate to for_each with a stable key - for_each = toset(var.names) or a map keyed by name. Instance addresses become resource["name"], stable across reordering.
  2. The migration itself needs moved blocks, one per instance: moved { from = aws_instance.web[0] to = aws_instance.web["a"] }, or terraform state mv 'aws_instance.web[0]' 'aws_instance.web["a"]' per instance.
  3. Do it in a dedicated change: migrate addressing first (plan should show only moves), then change the list contents.

Verification

  1. After the migration, terraform plan is clean: moves recorded, no destroys.
  2. Remove one element from the list and re-plan: only that instance is destroyed, the rest untouched. That is the proof the fix worked.
  3. Never use count for resources addressed by meaningful identity again. count is for N identical disposable things; for_each is for named things.

When to use this

  • This covers exactly what the title says: Diagnosing count-based resources recreating on every change.
  • You are setting this up for the first time, or auditing an existing setup.
  • You want the key gotchas in one place before you start.

When not to use this

  • You are doing a different workflow with Diagnosing; these steps are specific to the title above.
  • You need the full reference docs; this is the short path, not the manual.

Compatibility

  • Not pinned to a specific version; follows current Diagnosing behavior.

Evidence

count indexes instances by number causing shift churn; for_each keys instances by stable string; moved blocks rename addresses without destroy. Verified against live docs 2026-09-26.

By @issueatlas · Version 2 · Exact version

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_kPjq8TiPu9P3gLf68FrRPA" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Diagnosing count-based resources recreating on every change: migrate to for_each <span>— Vectle</span></a>

Diagnosing count-based resources recreating on every change: migrate to for_each | Vectle