Skip to main content

Terraform

Why does Terraform need a state file at all?

Short answer

Because your configuration says what should exist, and the cloud says what does exist, and neither tells you which real resource corresponds to which block of code. State is that mapping — and it is also the only record of things you asked for that the provider does not report back.

The constraint behind it

Consider what Terraform has to work out. Your configuration declares `aws_instance.web`. The provider can list every instance in the account. Nothing in either of those says which instance *is* `aws_instance.web` — cloud resources are identified by opaque IDs that your code never mentions.

Without a mapping, the only options are both bad. Terraform could match on attributes, which breaks the moment two resources look alike or one is renamed. Or it could tag everything it creates and search by tag, which fails for the many resource types that do not support tags and turns every plan into a full inventory scan.

There is a second, less obvious reason. Some things you declare are not recoverable from the provider afterwards: a generated password, a value the API accepts and never returns, an attribute that exists only at creation. If Terraform did not record them, it could not tell whether they had changed and could not manage them at all.

And a third: dependency order. Deleting resources safely requires knowing what depended on what *at the time they were created*, which your current configuration cannot tell you — you may have already removed the block that created the dependency.

◈ If it were the other way

What that system would look like

A stateless Terraform would have to reconstruct reality on every run by querying every resource type in every region and matching each one against your configuration. Plans would take a very long time and would be wrong whenever two resources were similar enough to confuse the matcher.

Renaming a resource in code would be indistinguishable from deleting one and creating another, because nothing would connect the old identity to the new name. Every refactor would be a rebuild.

Generated values would be lost. A password Terraform created and the provider never returns would be unknowable, so it could never be rotated or referenced — and `terraform destroy` would have no reliable order to work in, because dependency information would have to come from a configuration that no longer describes what exists.

Some tools do work this way, and they cope by being much more constrained: they either require every resource to carry an identifying tag, or they only manage resources they can unambiguously name. That is a real design and it buys statelessness by giving up generality.

◆ What it buys you

  • A stable identity for each resource across renames and refactors, so changing a block's name is a move rather than a rebuild.
  • Fast plans. Terraform refreshes what it knows about rather than discovering the account from scratch.
  • The ability to manage write-only values — generated passwords, keys, anything the API accepts and does not return.
  • A correct destruction order, recorded when resources were created rather than inferred from a configuration that may have changed.

◑ What it costs you

  • State becomes a critical artefact with its own operational needs: remote storage, locking, versioning, backups. Losing it does not destroy your infrastructure, but it does mean Terraform no longer knows it exists.
  • It contains secrets. Any generated password or key is in there in plain text, which makes the state backend a security boundary — and a state bucket where every engineer can read objects is one of the most common audit findings there is.
  • Concurrency has to be managed, which is where locking comes from and why a stuck lock is a routine operational problem.
  • It can disagree with reality, and that disagreement is drift — a whole category of problem that exists only because there is a third thing to be out of step with.

Where it bites in practice

Most sharply the first time somebody deletes a resource in a console and expects Terraform not to care. State still says it exists, so the next plan proposes creating it — which reads as Terraform inventing work. It is doing precisely what it was built to do: reconciling three sources of truth, one of which somebody changed without telling it.

What comes next

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere