Losing or corrupting state is the worst common Terraform accident.
State is a JSON file (terraform.tfstate by default) that records, for each resource address, the real object it corresponds to: its ID and all known attributes. Terraform needs it because:
- APIs can't tell which objects your configuration created;
aws_instance.webmaps toi-0abc...only through state. - It stores attributes for dependencies and speeds up plans.
- It remembers resources you deleted from the configuration, so it can destroy them.
During plan, Terraform refreshes state by reading each object's current settings, then diffs your configuration against them.
Rules:
- Never commit state to git. It contains secrets in plain text (database passwords, private keys), and two people with different copies will fight. Add
*.tfstate,*.tfstate.*and the.terraform/directory to.gitignore, but do commit.terraform.lock.hcl. - Store it in a remote backend with locking for any shared project (next lesson).
- Don't edit it by hand. Use
terraform state list,state show, and the refactoring tools (moved,import,removedblocks) to change it safely. - Losing state doesn't delete infrastructure, but Terraform forgets it exists; the next apply tries to create duplicates. Recovering means importing everything again.
Example
terraform state list
# aws_subnet.app
# aws_vpc.main
terraform state show aws_vpc.main | head -5
# resource "aws_vpc" "main" {
# arn = "arn:aws:ec2:eu-west-1:123456789012:vpc/vpc-0a1b2c3d"
# cidr_block = "10.0.0.0/16"
# id = "vpc-0a1b2c3d"
cat >> .gitignore <<'EOF'
.terraform/
*.tfstate
*.tfstate.*
*.tfplan
EOFRemember
- State maps addresses like aws_vpc.main to real IDs
- It holds secrets: never commit it; keep it remote with locking
- Change state with state commands and refactoring blocks, not by hand
Watch out for
- Committing terraform.tfstate to a repository, leaking secrets and causing conflicting copies.