> ## Content Index
> Fetch the complete content index at: https://debugly.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# Reviewing a Terraform Diff for the Resource It Will Replace
- URL: https://debugly.dev/reviewing-terraform-force-replacement/
- Published: 2026-10-09T13:49:00.000Z
- Updated: 2026-10-17T05:56:26.000Z
- Description: A one character change to an immutable attribute shows as a tidy edit in the diff and executes as a destroy plus create, and the review that prices the edit…
- Author: Rohit Bhadani
- Tags: Code Review, DevOps, Tooling

The plan said one resource would be updated, and the apply destroyed a database and created a new one, because the attribute that changed is immutable, and Terraform's answer to an immutable change is replacement, and the diff's presentation, a line with a tilde and a hash, read as an edit, while the execution was a deletion of the old and a creation of the new, with the old's data gone, which is the distance between the diff's typography and its effect, and the distance is the review's entire subject.

This is the review guide for the force replacement, the change that presents as an update and executes as a destroy plus create, and the checklist that prices the replacement, because the replacement is the change, and the edit is the costume.

This was Terraform 1.7 managing cloud resources, and the destroyed resource was stateful, which is the property that turns a replacement into an incident.

## The presentation versus the execution

The plan output marks each resource with an action, create, read, update, destroy, and the replacement is marked as update with a note that replacement is required, or as a destroy and create pair, and the note is easy to miss, because it is a suffix on a line in a long plan, and the reviewer's eye, trained to read diffs as edits, reads the tilde as change in place, and the in place is the assumption, and the assumption is wrong for immutable attributes, where the provider cannot mutate and must replace.

The review's first move is therefore to read the plan's action column, not the code's diff, because the action column is the execution's vocabulary, and the code's diff is the intent's vocabulary, and the two disagree exactly at the immutable attribute, and the disagreement is the risk.

## Why the replacement is the dangerous change

A destroy plus create is dangerous in proportion to the state the old resource holds, and the state is the property the review must price. A stateless resource replaced is a blip, a new instance, the same config, no loss. A stateful resource replaced is a data event: the database whose storage is tied to the resource, the queue whose messages live in it, the IP that clients have cached, and the replacement's cost is the data's fate, which the plan does not print, because the plan knows the resource graph, not the data's value.

The second danger is the identity change: the replacement has a new id, a new address, a new endpoint, and the consumers of the old identity, the connection strings, the DNS, the allowlists, now point at a corpse, and the outage is the gap between the destroy and the consumers' discovery, which is the failover lesson from [the failover that promoted a replica hours behind](https://debugly.dev/pg-failover-replica-hours-behind/), and the common root is the property, not the platform.

## The review checklist

For every resource the plan marks for replacement, the review asks four questions, and an unanswered one is a block.

**What state does the old resource hold, and where does it go.** If the resource owns storage, the replacement's destroy deletes it unless the provider detaches it, and the review requires the data's destination named, a snapshot, a migration, a detach, because the default destination is gone, and gone is not a migration plan.

**What consumes the old identity, and how do they learn the new.** The consumers of the endpoint, the address, the id must be updated atomically with the replacement or tolerate the gap, and the review names them and the mechanism, a DNS with a TTL, a config with a reload, and the gap's duration, because the gap is the outage, and the gap is invisible in the plan.

**Is the replacement ordered, and is the old kept until the new is ready.** A create before destroy, where the provider supports it, is the safe order, and the review checks the plan's order, because destroy before create is the window where nothing serves, and the window is the incident, and the order is a property the plan states and the review must read.

**Can the replacement be rolled back.** The destroy of the old removes the rollback target, so the review asks what remains to roll back to, a snapshot, the previous config, and if the answer is nothing, the replacement is one way, and one way changes deserve the review's highest suspicion, per the rollback discipline in [the rollback that the CDN kept serving for an hour](https://debugly.dev/rollback-cdn-still-serves/), generalised: a change without a rollback is a decision, and decisions get the senior review.

## The plan flags that hide the replacement

The review should also know the plan's euphemisms, because the replacement arrives under several. The `forces replacement` suffix on an attribute, the `# must be replaced` comment, and the `-/+` symbol pair, all mean destroy plus create, and all are easy to skim past, and the review's habit is to grep the plan for the replacement markers before reading anything else, because the replacements are the few lines that price the change, and the rest of the plan is the updates, which are cheap.

The `prevent_destroy` lifecycle flag is the tripwire for the stateful resources, and its presence in the config is the review's ally, because it makes the dangerous replacement fail the apply, which is the boundary enforced, and the review checks that the stateful resources carry it, because the flag is the schema-level statement that the resource's replacement is an incident, which is the truth the flag enforces.

## What I would do differently

I have chased this from the plan end and from the code end, and the truth was in the hand-off, as it usually is.

## If it happens again

An immutable attribute changed is a replacement, a destroy plus create, presented as an edit, and the review must price the replacement: the state's destination, the consumers of the old identity, the create before destroy order, and the rollback that remains, with the plan's action column as the source of truth and the replacement markers as the first read.

The one character change was not small. It was a deletion wearing an edit's clothes, and the clothes are what the diff prints, which is why the review that reads the typography prices nothing, and the review that reads the action column prices the incident, which is the whole job, in two symbols.

---

Published on [debugly.dev](https://debugly.dev/) by [Rohit Bhadani](https://debugly.dev/about/) | Founder of [Krova Cloud](https://krova.cloud/?ref=debugly.dev)