Local Terraform state works fine when you are the only one touching infrastructure. The moment a second engineer runs terraform apply, you have a race condition problem. Remote state with locking is not optional for production — it is the baseline.
Why local state breaks in teams
The terraform.tfstate file is the source of truth for what Terraform thinks exists in your cloud account. If two people apply changes simultaneously without locking, state gets corrupted. If someone forgets to commit the file, state diverges from reality. If the file is checked into git, secrets in outputs become a security incident waiting to happen.
Setting up S3 remote backend with DynamoDB locking
AWS S3 + DynamoDB is the most common pattern. S3 stores the state file, DynamoDB provides distributed locking.
terraform {
backend "s3" {
bucket = "my-org-terraform-state"
key = "prod/network/terraform.tfstate"
region = "ap-south-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
Workspaces vs directory-per-environment
Terraform workspaces let you keep multiple state files within the same backend key prefix. They are great for ephemeral environments (e.g., per-PR preview stacks) but I prefer directory-per-environment for long-lived infra. It makes the blast radius explicit: you must cd prod/ before you can touch production.
Useful commands when things go wrong
# List all resources tracked in state
terraform state list
# Remove a resource from state without destroying it
terraform state rm aws_instance.legacy
# Import an existing resource into state
terraform import aws_s3_bucket.data my-existing-bucket
# Force-unlock a stuck lock (use with care)
terraform force-unlock LOCK_ID
Key takeaways
- Always use a remote backend with state locking in any team environment.
- Enable S3 versioning — it is free state history and your undo button.
- Never store sensitive outputs in state if you can avoid it.
- Prefer directory-per-environment over workspaces for production infrastructure.