State — The Site Register
When the contractor finishes building a villa, the builder doesn't rely on memory. A site register records exactly what was built, where it is, and how it was configured. If a wall is changed later, the register is compared against the blueprint to decide what needs fixing.
That register is Terraform state — a JSON file (default terraform.tfstate) that maps every resource in your configuration to its real-world object. Without it, Terraform would have no idea whether your blueprint is already built, partially built, or completely absent.
Why State Exists
resource "aws_s3_bucket" "archive" {
bucket = "campus-library-archive"
}
The first time you apply, state records: "this bucket exists, with id campus-library-archive." On the second apply, Terraform reads state, sees the bucket already exists, and plans 0 to add. Remove state, and Terraform would try to create it again — and fail, because it already exists.
State also stores sensitive values (database passwords, keys) and the metadata needed for every subsequent plan.
State is the truth about reality. Your .tf files are the blueprint; the .tfstate file is the register of what was actually built.
Inspecting the Register
terraform state list
aws_s3_bucket.archive
aws_security_group.web
aws_instance.app
terraform state show aws_s3_bucket.archive
# aws_s3_bucket.archive:
resource "aws_s3_bucket" "archive" {
arn = "arn:aws:s3:::campus-library-archive"
bucket = "campus-library-archive"
...
}
Changing the Register
Sometimes reality and the register disagree, or a resource moves into or out of Terraform's care.
| Command | What it does |
|---|---|
terraform state mv <from> <to> | Re-address a resource (e.g., after renaming in config) |
terraform state rm <addr> | Stop tracking a resource without deleting it |
terraform state pull | Print the state to stdout |
terraform state push | Write a state file from disk (use with care) |
state rm untracks a resource but leaves it running in the cloud — an untracked resource is orphaned infrastructure that no one manages. Use import to bring resources into state instead of abandoning them. See Troubleshooting.
Importing — Recording Something Already Built
If infrastructure was created manually (clicking in the console), bring it under management:
terraform import aws_s3_bucket.archive campus-library-archive
Now the resource is in state, and the next plan will show what (if anything) differs from the blueprint.
Backends — Storing the Register Safely
By default state lives in a local terraform.tfstate file on your machine. That's fine for learning, but useless for a team — five engineers each holding their own register will build over each other.
A backend stores state in a shared, central location. The standard cloud choice is S3 for storage + DynamoDB for locking:
terraform {
backend "s3" {
bucket = "campus-library-terraform-state"
key = "colony/terraform.tfstate"
region = "eu-west-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
Two things happen automatically:
- Central storage — everyone reads and writes the same register.
- Locking — before planning/applying, Terraform takes a lock; while locked, other runs wait or fail. This is the "only one contractor on site at a time" rule, and it prevents two engineers from planning against different versions of reality.
Local backend = your personal notebook. Remote backend = the central archive. Teams must use a remote backend, or state lock errors are the least of their problems.
Drift — When Reality Drifts from the Register
Drift is when the live cloud resource no longer matches state — someone deleted a bucket, changed a tag in the console, or scaled an instance by hand. Your register is now stale.
terraform apply -refresh-only
This updates state to match reality without making changes — then terraform plan shows the true difference between the blueprint and reality, so you can decide to re-apply the blueprint (fixing the drift) or keep the change.
The Golden Rules of State
- Never hand-edit
.tfstate— it breaks the mapping - Never store state in Git — it may contain secrets
- Never let state become local-only on a team
- Always use locking with a remote backend
- Back up state — it's your infrastructure's memory
Treat state like the building's ownership deed: it's small, precious, and the source of truth. Handle it with the same care in interviews — questions about state are the most common Terraform interview questions there are.
Next, turn the single-run commands into a repeatable workflow and team ritual.