A resource sets lifecycle { ignore_changes = [tags] } because an external cost tool rewrites tags. A refresh-only plan still reports the tags as changed outside of Terraform. An engineer thinks ignore_changes is broken. What explains the behavior?
Select an answer to reveal the explanation.
Short Explanation
Think of ignore_changes as a 'don't fix this' sticky note, not a blindfold. Terraform still looks at the tags during refresh and writes what it sees into state; it just won't plan to change them back on you. The trap is believing it hides the drift entirely.
Full Explanation
The ignore_changes lifecycle argument lists resource attributes that Terraform should ignore when planning updates to an existing object. The arguments are still used when creating the object, but later differences between configuration and the real object do not produce update actions. It does not change how refresh works: during any plan, Terraform reads each remote object and updates its record of the current attribute values, and refresh-only mode exists precisely to show and record those external changes. So the refresh-only plan correctly reports that the tags differ from the previous state snapshot, and applying it would record the new values without touching the infrastructure, while a normal plan proposes no tag update. The idea that ignore_changes only applies at creation inverts the documented behavior; it is honored on updates, and creation is when the configured values are used. Refresh-only plans never revert anything, since they make no infrastructure changes at all. There is no setting that names an external process; ignore_changes takes attribute names, or the all keyword. Exam caveat: ignore_changes applies only to attributes defined by the resource type and cannot target meta-arguments. Operational check: run a normal plan and confirm it shows no tag update; then apply refresh-only if you want state to reflect the tool's tags.