TerraformIX · State: The Core Production ConceptState
State: The Core Production Topic
What you'll learn
- Explain why Terraform requires state
- Describe what state contains and what it does not
- Recognise the consequences of state and reality disagreeing
- Identify why state is the deepest production topic in the course
Prerequisites
Verified against Terraform CLI 1.9.x · OpenTofu 1.7.x · HCL 2.0 · bpg/proxmox provider 0.66+ · hashicorp/local provider 2.5+ · hashicorp/null provider 3.2+ · hashicorp/random provider 3.6+ · hashicorp/http provider 3.4+ · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · 2026-08-12
State is the deepest production topic in this course. Every other Terraform concept — modules, environments, CI/CD, policy — is a tool for controlling the blast radius of state. If you read only one lesson in the course, read this one.
Why Terraform needs state
Three reasons, all of them operational.
State lets Terraform know what already exists
Without state, Terraform would have to ask the provider for every resource on every run. For a 5,000-resource estate, that is 5,000 API calls before any work begins. With state, Terraform reads the local JSON and asks only about resources it suspects might have changed.
State lets Terraform map resource addresses to real-world objects
A terraform plan needs to know: “for the resource declared as
aws_instance.web in the configuration, what is the corresponding
EC2 instance ID in AWS?” The provider returns that ID once, after
the first apply. The state stores it. The next plan does not have
to ask again.
State lets Terraform propose safe operations
Without state, Terraform cannot know whether an apply would:
- Create a brand-new resource (resource not in state, not in real world).
- Update an existing resource (resource in state, matches real world, configuration differs).
- Destroy an existing resource (resource in state, matches real world, no longer in configuration).
- Replace an existing resource (resource in state, configuration requires a change that the provider cannot make in-place).
Each of these decisions is operational. Create-new in production costs money. Destroy on a database is catastrophic. The state file is what lets Terraform make the correct decision.
What state contains
A state file is JSON. The fields that matter operationally:
| Field | What it holds | Why it matters |
|---|---|---|
version | State schema version | Determines which terraform version can read it |
terraform_version | The version that wrote the file | Detects stale state |
serial | Monotonic counter | Bumped on every write; ordering signal |
lineage | UUID | Identifies the lineage; rolled on terraform state mutations |
outputs | Last computed values | Available for terraform output and downstream config |
resources | One entry per resource | The actual mapping from address to real-world ID |
resource_instances[i].attributes | The attributes the provider returned | What was true at the last refresh |
resource_instances[i].dependencies | Computed dependencies | Cross-reference for ordering |
The state does not contain:
- The users
.tfconfiguration. - The variable values that resolved during the last apply.
- The output values that have not been computed.
- Any history of past plans.
The state is a snapshot of what Terraform believed the world looked like at the last refresh. It is not a journal.
What state does not know
The state knows what the provider last told it. It does not know what the provider did not report. A typical example:
resource "aws_instance" "web" {
ami = "ami-0e1bed4f"
instance_type = "t3.medium"
tags = {
Name = "web-01"
}
}
After apply, the state has the instance_type, the ami, the id,
and the tags. It does not have the route table, the security group
ingress rules, the EBS volume ID, the IAM instance profile, or any
of the dozens of real-world attributes a describe-instances would
return. The state is a summary along the schema the provider
chose to expose.
This is intentional. Storing every attribute would make the state unboundedly large and would surface every API change as a Terraform state change. The provider decides what to expose; Terraform stores what it is told.
The drift problem
State is a snapshot of the past. The real world is now. The two can disagree:
On Monday: Terraform applies; state records "web-01 has tags {Name=web-01}"
On Tuesday: An engineer runs `aws ec2 create-tags --resources i-0abc
--tags Key=Environment,Value=production`
On Wednesday: Terraform runs again. Configuration says
tags = {Name = "web-01"}. State says tags = {Name = "web-01"}.
Provider refresh says tags = {Name = "web-01", Environment = "production"}.
What does Terraform do?
The answer is nothing, until the engineer adds Environment = "production" to the configuration. The provider refresh detects
the drift, Terraform updates its internal model, and the next plan
shows:
~ tags["Environment"] = "production" → "production"
It does not propose to remove the tag. It believes the tag is
already in the real world. The configuration was always silent on
Environment; the state was less informative than reality.
What happens when state is wrong
State is wrong in many ways. The course treats each in depth later, but the four canonical cases are:
| Failure | Symptom | Recovery |
|---|---|---|
| State is lost | Plan proposes to create everything from scratch | Restore from backup; never apply blindly |
| State is corrupted | terraform plan fails with a JSON parse error | Restore from backup; do not edit by hand |
| State is stale | Plan proposes unexpected changes | Refresh first; investigate the diff |
| State is wrong | Plan proposes a correct change to the wrong resource | Compare every address to the real resource; fix manually with terraform state |
The wrongest thing an engineer can do at this point is delete the
state file and rerun terraform apply. That tells Terraform “the
real world is empty”, and the next plan will propose to create
duplicate resources, fail to do so in production, or — if the
provider permits overwriting — destroy and recreate real
infrastructure without warning.
What “lost state” means in practice
If state is lost, three things are true simultaneously:
- The real-world infrastructure still exists.
- Terraform does not know the real-world infrastructure exists.
- The configuration file describes from scratch what should exist.
The plan will then propose to create everything from scratch. If that plan is applied, Terraform will try to create duplicates of everything that exists. The providers behaviour depends on the resource type:
- Some resources will fail because the real-world identifier (e.g. a DNS name or a S3 bucket name) is unique.
- Some resources will silently overwrite the existing one.
- Some resources will create shadow copies in addition to the originals.
The recovery procedure is:
- Stop. Do not apply.
- Investigate what the real world looks like.
- Restore state from backup, or rebuild state by importing each resource individually.
- Plan again and verify the plan is empty.
The course has a dedicated lab for this in Part CXI.
Treat state as production data
The state file:
- May contain secrets. A database
passwordargument is stored in state in plain text unless markedsensitive. Adeploy_keyis stored in plain text. The course returns to this in Part LIV. - Must be encrypted at rest. If the state is remote, the remote backend should encrypt it. If the state is local, the disk should be encrypted.
- Must be access-controlled. Anyone who can read the state can read the secrets and the topology. Anyone who can write the state can rewrite Terraforms model of the world.
- Must be backed up. The course recommends daily backups with offsite copies, and treats the loss of state as a data-loss incident.
- Must not be in Git. The state is a binary blob; it grows monotonically; it changes on every apply; and committing it leaks the topology and often the secrets.
The mental model
A clean way to think about Terraform state:
Configuration ─┐
│ terraform plan
State ─┤ ────────────────► Plan output
│
Real world ─┘
(provider refresh)
The plan is a proposal based on the three sources of truth.
- If the configuration matches what state believes about the real world, the plan is empty.
- If the configuration differs from state, the plan proposes to change the real world.
- If state differs from the real world, the plan proposes to change the real world based on a stale model — the configuration is applied to whatever state thinks, which may not be the real world.
The plan output is the only place where Terraform tells you what it is about to do. The plan is not a side-effect; it is the operational artefact. Read it. Compare it to your expectation. Apply only when the plan matches what you want.
What the state tells you
The state is the only honest record of what Terraform believes exists. If you want to know what Terraform thinks your infrastructure is, read the state.
# List everything Terraform knows about
terraform state list
# Show the details of one resource
terraform state show aws_instance.web
# Show the full state
terraform show
These commands are read-only. The state-mutating commands
(state mv, state rm, state replace-provider) are the
subject of Part XXXVI.
What you should take away
- State is the central production concern. Every other Terraform concept serves state.
- State may be wrong. Backup, version, and audit state as carefully as you would any production database.
- The plan is the proposal. Read it. Compare it. Do not apply without understanding it.
- State and reality can disagree. When they do, the plan proposes to apply the configuration to whatever Terraform believes, which may not be what is real.
- State is sensitive. It is not in Git. It is encrypted at rest. It is access-controlled. It is backed up.
What comes next
The next lesson is local state: what terraform.tfstate looks
like on disk, why it is brittle, and why production teams move
to a remote backend.
Knowledge check · 7 questions
Q1. Why does Terraform need state?
Q2. Where should state be stored for production?
Q3. A lost state means lost infrastructure.
Q4. What is the role of the dependency lock file?
Q5. Which of the following are stored in state? (Select all that apply.)
Q6. What is the role of state in plan output?
Q7. A team runs plan and sees no changes. The real world has drifted. They run apply; the apply also shows no changes. What should they investigate?
Passing score: 75%. Answers are checked in this browser.