See it as a diagram
Everything below, as a diagram you can edit. Describe yours and see it in seconds.
No account needed · Editable canvas, not a picture
What the diff hides
Replacement is the first hidden thing. Many attributes force a destroy and create rather than an update, and the HCL line that triggers it looks the same as one that does not. Only the plan says forces replacement, and only a human knows that the resource in question holds data.
Reach is the second. A one-line change inside a shared local module lands in every stack that calls it. The diff shows the module file; it does not show the four stacks downstream, and the reviewer who does not already know the repository has no way to find out from the pull request.
Shape is the third. A change that adds a resource in a different module, moves a subnet to another VNet, or introduces a dependency between two previously independent modules alters the architecture. It is exactly the kind of change worth a second opinion, and exactly the kind that reads as unremarkable in a unified diff.
A checklist that catches the expensive mistakes
Run these in order. The first three are about not losing data, the next three are about not surprising anyone, and the last is about not making the next reviewer suffer.
Point three is cheap to automate: moved blocks, available since Terraform 1.1, let a refactor rename addresses without a destroy and create, and their absence in a rename is a review finding. Point one can be automated in the pipeline too, since terraform plan -detailed-exitcode returns 0 for an empty diff, 1 for an error, and 2 when the plan contains changes, which is enough to route a plan with replacements to a human.
1 plan output: any "forces replacement" on a stateful resource? 2 for_each / count keys: did any key change, renumber, or reorder? 3 moved / removed blocks present where a refactor renamed addresses? 4 is the touched module called by more than one stack? 5 module or provider version bumps, and are they pinned? 6 backend, state key, or workspace changes? 7 does the change alter the architecture, and is the diagram going to say so? # in CI: exit 0 = no changes, 1 = error, 2 = changes present terraform plan -detailed-exitcode -out=tfplan
Where a diagram helps, and where it does not
The plan answers create, replace, destroy. Nothing else can, and no diagram substitutes for reading it. What the plan does not answer is what is connected to this, because plan output is a list, and reach is a graph.
A structural view answers reach. Connect the repository a second time on the feature branch, since a project is bound to a branch or a tag, and you get the shape that branch produces: modules as zones, references resolved through outputs into labelled edges, registry modules with their versions. Comparing it to the project synced from main shows what the change did to the structure, which is the part reviewers most often get wrong.
The comparison holds up because node ids come from the Terraform address rather than from any wording, with uninformative resource names such as this, main, and default dropped from the id. The same resource is the same node on both branches, so a new zone means a new module, a new arrow between zones means a coupling that did not exist yesterday, and a node that moved from one zone to another means a boundary changed.
To be clear about scope, Datadef does not post comments on pull requests and does not read plan files. What it does is keep a branch-scoped architecture view that regenerates on demand, including from a coding agent session over MCP, where repo status and refresh tools let the agent bring the diagram up to date after the change merges.
Put the check in CI, not in memory
FAQ
What should a Terraform code review check first?
Can I see the architecture a branch produces before merging it?
Does an architecture diagram replace reading terraform plan?
How do I catch a change that would recreate a database?
Who should review infrastructure changes?