State Hygiene: Never Hand-Edit
Refactor safely with import, mv, and rm — and treat manual edits of the state JSON as a fireable offense.
State is a database, not a text file. The moment you open terraform.tfstate in an editor and start deleting braces, you are one typo away from Terraform trying to recreate live production resources.
The three commands that keep you safe
terraform state mv— rename or move a resource after refactoring code, so Terraform sees a rename instead of destroy-and-recreate.terraform state rm— stop managing a resource without destroying the real thing (great before deleting a module).terraform import(or animportblock) — adopt a resource that already exists in the cloud.
Always work from a backup
Before any surgery, run terraform state pull > backup.tfstate. If something goes sideways, terraform state push puts it back. With a versioned S3 backend you also have automatic history.
Example
# Take a safety copy first — always
terraform state pull > backup.tfstate
# Renamed the resource in code? Tell state, don't recreate.
terraform state mv 'aws_instance.web' 'aws_instance.frontend'
# Moved a resource into a module
terraform state mv 'aws_s3_bucket.data' 'module.storage.aws_s3_bucket.data'
# Stop managing something without deleting it in the cloud
terraform state rm 'aws_iam_user.legacy'When to use it
- An engineer renames a resource block in HCL and runs terraform state mv to update state, avoiding a destroy-and-recreate of a production database.
- A team decommissions a legacy resource by running terraform state rm to stop tracking it without deleting the actual cloud object.
- After manually deleting a test instance in the console, an operator runs terraform state rm to prevent the next plan from erroring on a missing resource.
More examples
Move resource after rename
Renames the resource's state key to match the HCL refactor, preventing Terraform from destroying and recreating the cluster.
# HCL renamed: resource "aws_rds_cluster" "db" -> "primary"
# Without mv, Terraform would destroy old and create new!
terraform state mv \
aws_rds_cluster.db \
aws_rds_cluster.primary
# Confirm plan shows 0 changes
terraform planRemove from state without destroying
Removes a resource from state without touching the cloud object, useful when handing off ownership to another team or tool.
# Stop managing a resource without deleting it
terraform state rm aws_s3_bucket.old_logs
# Verify it is gone from state
terraform state list | grep old_logs
# (no output — Terraform no longer tracks it)
# The bucket still exists in AWSCreate backup before state surgery
Shows the safety pattern of pulling state to a timestamped backup file before any state surgery, enabling rollback if needed.
# Always back up state before mv/rm/push
terraform state pull > backup_$(date +%Y%m%d_%H%M%S).tfstate
# Perform the surgery
terraform state mv aws_instance.old aws_instance.new
# If something goes wrong, restore:
# terraform state push backup_20240715_120000.tfstate
Discussion