Every team has the story: a three-line YAML change sails through review with a thumbs-up in ninety seconds, and twenty minutes after deploy, production is down. Nobody was careless by their own standards. The reviewer applied the calibration that works for application code, where small diffs are usually safe diffs. To review infrastructure as code well, you have to unlearn that instinct, because in config the two are unrelated, and often inverted.
The short answer: Config and infrastructure diffs under-signal: they look tiny while touching everything. Review them by asking four questions the diff does not answer. Which environment does this actually hit? What defaults change silently underneath it? What permissions or secrets widen? How does it roll back? And insist on plan output as the review artifact, because the diff shows your edit while the plan shows what the platform will do.
Why config diffs under-signal
Application code advertises its complexity. A 400-line refactor looks scary and gets attention; a two-line change to a values file looks trivial and gets a glance. But config is dense with leverage: one value in a base template is inherited by every environment and every service that extends it. Diff size is a terrible proxy for risk, which is the whole argument of reviewing by blast radius, and infra is where the mismatch is worst. The smaller and more central the file, the more it usually touches. A reviewer who spends ten minutes on a three-line Terraform change is not being slow. They are being calibrated.
Which environment does this actually hit?
The first question, and the one most often skipped. Overlays, inheritance chains, workspaces, and templating all mean the file path lies about the scope: a change to base/ hits everything that inherits from it, and a file named staging.yaml can feed a module that production also consumes. Make the author say it in the PR description: which clusters, which accounts, which stages this lands in. The postmortems where a staging tweak turned out to be global almost always contain a reviewer who assumed the filename was the answer.
A checklist to review infrastructure as code
- Environment scoping. Name every environment the change touches. If the author cannot enumerate them, that is the review finding.
- Implicit defaults. A provider bump or chart upgrade can change defaults underneath a file that did not change at all. If versions moved, ask what defaults moved with them.
-
Secrets and permissions. Any widening of IAM roles, security groups, or service account scopes is a security review, not a config review. Treat a new
*in a policy as a finding until justified. -
Plan output in the PR. Require
terraform plan,kubectl diff, or the equivalent as a PR artifact, generated by CI so it reflects real state. - Rollout and rollback story. How does this deploy, and does reverting the commit actually revert the change? Some infra changes are one-way doors the same way database migrations are: the revert is a second migration, not an undo.
The plan is the review artifact
The diff is what you wrote. The plan is what will happen, and they diverge constantly: state drift, module version bumps, and provider defaults all produce changes the diff never mentions. Reviewing a Terraform PR without plan output is reviewing a function by reading its name. The workable pattern is CI posting the plan into the PR on every push, so the reviewer reads intended edits and actual effects side by side. Read the plan with a simple priority: anything that destroys or replaces a resource first, permission changes second, everything else after. A plan that replaces a database to rename a tag is exactly the kind of thing the diff will never tell you.
AI wrote the YAML; who owns the why?
More and more infra is generated: an agent writes the Terraform, the human skims it, CI is green, merge. Osmani made the general argument that generation got cheap while understanding stayed expensive, and infra is where that gap bites hardest, because generated config looks authoritative while embedding defaults nobody chose. The instance size, the retention window, the ingress rule: were those requirements, or fill? The review has to distinguish the two, and the author has to capture the intent while it still exists. Six months from now, someone will stare at that retention value during an incident and need to know whether it was a decision or an accident. The PR is the only place that answer can live.
None of this makes config review slow. It makes it proportionate: ninety seconds was never the real cost of that three-line change, it was just the part paid before the incident.
Frequently asked questions
Why are small config changes so risky to review?
Because diff size and blast radius are unrelated in configuration. A three-line YAML change can retarget an environment, widen a permission, or change a default inherited by every service, while looking more boring than a 300-line refactor. Reviewers calibrated on application code give small diffs a glance, which is exactly backwards for infra.
Should terraform plan output be part of the pull request?
Yes. The diff shows what you edited; the plan shows what the platform will actually do, including changes pulled in by state drift, module updates, and provider defaults. Posting plan output in the PR, ideally generated by CI, turns review from guessing about effects into reading them. Destroy and replace lines deserve the most attention.
How should I review AI-generated Terraform or YAML?
Insist on the reasoning, not just the result. Generated infra tends to look plausible and complete while embedding defaults nobody chose deliberately. Ask which values were requirements and which the model invented, check permissions and network scope line by line, and record the intent in the PR while it still exists, because the prompt session will not survive.
Top comments (0)