You run terraform plan and see resources being destroyed and recreated. Nothing meaningful changed. No config drift. No API difference. Still, Terraform insists something is different.
The issue is not randomness. It’s identity.
When for_each keys are built from expressions that include fallback logic, formatting, or conditional repair, the final key can change even when your intent does not. Terraform does not track intent. It tracks the computed address.
That means a small change in how a string is constructed or a missing value is handled can shift the resource address. Once the address changes, Terraform treats it as a different object and plans a replacement.
The fix is not to avoid expressions. The fix is to separate concerns.
Normalize input once. Validate early. Keep identity stable. Let resource blocks consume clean data instead of constructing it.
If identity is stable, the plan becomes trustworthy. If identity is unstable, every plan becomes a risk.

