Terraform Remote State Locking with S3 and DynamoDB
Local state files don't survive a team. Two people running apply at the same time will race each other and corrupt state. The fix is a remote backend with locking.
Backend config
terraform {
backend "s3" {
bucket = "acme-tfstate"
key = "prod/network/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "tfstate-locks"
encrypt = true
}
}
Creating the lock table
aws dynamodb create-table \
--table-name tfstate-locks \
--attribute-definitions AttributeName=LockID,AttributeType=S \
--key-schema AttributeName=LockID,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
Useful one-liners
Check who's holding a lock right now:
aws dynamodb scan --table-name tfstate-locks --query "Items[].LockID.S"
Force-unlock after a crashed apply (only after confirming no one is actually running):
terraform force-unlock <LOCK_ID>
Migrate an existing local state file into the new backend:
terraform init -migrate-state
Once the backend is wired up, every plan/apply in the workspace acquires the DynamoDB lock first, so a second run just waits (or fails fast) instead of stomping on the first.