86

IaC: desired state + plan as review; state is a database with one-way doors

#
  • practice
  • established
  • config

Conflicts with: Immutable infra ↔ stateful systems

References: Terraform — lifecycle meta-argument

IaC is not “provisioning scripts” but a declaration of desired state with detectable drift: a manual change in the console is a divergence between code and reality that plan must reveal and the process must forbid creating. terraform plan is a review artifact on a par with a code diff: what gets reviewed is not the HCL but the change plan (“destroy and recreate” on a database is what the reviewer is looking for). The state file is a database, with all that implies: locking, backups; renaming a resource without moved {} = destroy/create — a one-way door (20) disguised as a refactoring.

Code example (config)
Terraform · HCLconfig
# non-destructive refactor — a moved block, not “terraform got it from the name”
moved {
  from = aws_msk_cluster.kafka
  to   = module.streaming.aws_msk_cluster.kafka
}

# the invariant lives in code, not in the reviewer's head
lifecycle {
  prevent_destroy = true   # on stateful resources; a plan destroying them fails CI
}

What prevent_destroy does not do. It protects a resource only while that resource is described in the configuration: delete the resource block itself and the protection leaves with it, and the resource gets destroyed. So the protection cannot live in HCL alone. You need: policy-as-code that fails a plan with a destroy on stateful resources; CI that applies the saved plan rather than one recomputed at apply time; a check for deleted resource blocks in the diff; tested backups and restore drills; and an explicit break-glass procedure. Separately: drift is visible only within what the provider is able to read.

“Cattle, not pets” is a rule about how things change, not about the kind of resource: you can replace wholesale whatever is recoverable from code and replicas, while anything holding the only copy of some state requires explicit protocols for migration, restore and version compatibility. Replicated state with a quorum, or object storage, is managed declaratively just like compute; a unique machine with a local disk is not, whatever its tag says. Confusing the two is the standard way to lose state. Drift detection is not a quarterly audit but continuous (plan on a cron with an alert on a non-empty diff): drift found a month later has already grown dependencies — Hyrum (16) for infrastructure.

Last technical review: 2026-08-04 · Reference · 112 principles