Terraform / Editorial solution guide

Unexpected replacement: identity change or resource semantics?

Separate address churn from provider-required replacement before choosing a refactor or approving removal.

About 3 min readContent reviewed

Read-only knowledge base ยท No public comments

Recognize the symptoms

A small source edit proposes removal and creation, or a renamed/keyed resource appears as an old instance disappearing and a new instance arriving. A create-before-destroy action still contains deletion.

The proposal may be legitimate resource replacement, an omitted moved block, a count-index shift, changed for_each keys, another provider version, or the wrong state context. Treat those as distinct hypotheses.

Understand the likely causes

  • Managed addresses include module paths and instance keys; changing them can change ownership interpretation. Independently, a provider can require replacement when particular arguments change.
  • A source diff alone does not show data, downtime, unique-name, quota, or dependency consequences. A wrong fix can preserve an address while concealing a legitimately different intended object.

Establish the proposed and existing identities

Record the exact approved configuration revision, provider selections, backend/state target, addresses, and proposed action sequence from authorized evidence. Preserve the original diagnostic and compare the old and new module paths and keys. Do not read private state into public logs or apply merely to discover which identity Terraform meant. This guide uses authored examples only and runs no plan, import, or state operation.

A rename can require explicit continuity

When the same already managed object should continue at a supported new address, a moved block can express that refactor. The complete synthetic root below assumes a prior terraform_data.legacy binding. It is independent of real infrastructure and is never evaluated against state. The old resource should not remain simultaneously declared as another desired object. A moved block is not a tool for suppressing a real attribute replacement or merging conflicting ownership.

hcl Complete illustrative rename contract
terraform {
  required_version = ">= 1.16.0, < 1.17.0"
}

resource "terraform_data" "catalog" {
  input = "atlas-lab"
}

moved {
  from = terraform_data.legacy
  to   = terraform_data.catalog
}

The block describes address continuity for the stated prior identity. It neither adopts an unmanaged object nor authorizes a different real object to reuse the binding. No state is inspected or changed.

Review key changes independently from payload values

The offline set comparison below shows an old worker key becoming jobs. It identifies removed and added declarations only, not actual provider actions. If the name is cosmetic and identity should continue, review a supported move. If the domain object genuinely changed, preserving the old identity may be wrong. Count-index reorderings deserve the same separation between stable identity and changing presentation.

python Compare two declared instance-key sets
before = {'worker'}
after = {'jobs'}
print('removed_keys=' + ','.join(sorted(before - after)))
print('added_keys=' + ','.join(sorted(after - before)))
Expected output
removed_keys=worker
added_keys=jobs

The output flags worker as removed and jobs as added. It reads no Terraform plan and decides neither that destruction is required nor that a moved declaration is valid. Those require ownership and resource semantics.

Review the remaining replacement reason and risk

If the address is stable, inspect changed arguments, lifecycle triggers, provider version behavior, and resource-specific replacement rules. create_before_destroy changes supported ordering, not uniqueness constraints or service readiness. prevent_destroy can block a proposal but does not recover data. Removing protection or ignoring every attribute merely to obtain a quiet plan hides the decision. Choose a supported transition with the responsible owner and a data/availability recovery plan.

Verify the fix

Verify the corrected source and intended identity through the independently authorized review workflow. The new proposal should preserve only the intended continuity and still expose every legitimate resource action. Recheck dependencies, outputs, data retention, quotas, and downtime. A reduced action count is not success if it now conceals the wrong object or an unsafe unreviewed transition.

Keep it from recurring

  • Use stable keys, version address refactors, retain moved history where upgrade paths need it, and review provider upgrades separately. Define lifecycle and backup policies before replacements rather than treating every delete/create pair as a cosmetic naming problem.

Official references