Sensitive data
State can contain IDs, attributes, and secrets. Encrypt it, restrict access, and do not commit local state or backups.
Chapter 5 of 24
State is a protected mapping from configuration addresses to real objects, not a cache to delete when plans surprise you.
moved block without replacement.State can contain IDs, attributes, and secrets. Encrypt it, restrict access, and do not commit local state or backups.
aws_subnet.app["az-a"] is the configuration identity used to find one remote object.
Remote backends serialize writes. Local state creates backup files; retain backend versions and recovery access.
moved changes an address in state. removed intentionally stops managing an object without deleting it.
terraform state list
terraform state show 'aws_subnet.app["az-a"]'
terraform import aws_vpc.existing vpc-123
tofu plan -refresh-onlyUse an import block when the import should be reviewed in configuration; use the command for an explicit one-time operational action. A removed block is not a delete request. A moved block belongs with the refactor so every environment can make the same address transition.
Production state should use an encrypted remote backend with versioned backups and a lock mechanism. Never paste a state file into a ticket or chat; it can expose values that plan output redacts.
Open labs/05-state/main.tf and refactor.tf. The committed end state uses terraform_data.current_name; the moved block maps the old address.
(
set -e
workdir=$(mktemp -d)
trap 'rm -rf "$workdir"' EXIT
cp learn-terraform/labs/05-state/main.tf learn-terraform/labs/05-state/refactor.tf "$workdir"
cd "$workdir"
mv refactor.tf refactor.tf.disabled
perl -0pi -e 's/current_name/legacy_name/g' main.tf
tofu init -backend=false && tofu apply -auto-approve
perl -0pi -e 's/legacy_name/current_name/g' main.tf
mv refactor.tf.disabled refactor.tf
tofu plan -out=rename.tfplan
tofu show rename.tfplan
tofu apply rename.tfplan
tofu state list
tofu destroy -auto-approve
)The saved final plan must say the legacy address has moved to terraform_data.current_name and end with 0 to add, 0 to change, 0 to destroy. Review and apply that exact plan, then confirm terraform_data.current_name in state before cleanup. Any destroy/create pair means stop: check both addresses and the moved block before apply.
cd learn-terraform/labs/05-state
terraform init -backend=false
terraform state list
terraform plancd learn-terraform/labs/05-state
tofu init -backend=false
tofu state list
tofu plan| Expected | Meaning |
|---|---|
has moved to | The state address changes while the same remote object remains managed. |
0 to add, 0 to change, 0 to destroy | The rename caused no infrastructure action. |
-/+ or +/- | Not a successful address-only refactor; investigate before apply. |
| refresh-only difference | Observed remote drift needs a deliberate follow-up decision. |
After a failed or interrupted apply, run terraform plan or tofu plan, inspect state list and state show, and compare with the remote API. Import an object only when its configuration now declares the exact intended address. If an object must stop being managed but stay alive, review a removed block. Do not edit JSON state by hand unless following an established recovery procedure with a backup.
tofu state list after apply to see terraform_data.current_name.In the temporary directory, run tofu destroy -auto-approve, then remove that temporary directory. Do not delete a real project’s state file, lock, or backend object as cleanup.
moved block create a second object?No. It maps an existing state address to a new configuration address.
Only after confirming the original owner has stopped and the lock belongs to this workspace.
removed block do?It intentionally stops managing an object without requesting its deletion.
State is operational source of truth for object identity. Protect it, inspect it deliberately, and preserve identity with moved blocks during refactors.
Next: Chapter 6 will introduce variables, contracts, and modules.