Upgrade Terraform to 1.11 or later where native S3 state locking (`use_lockfile`) is generally available; in 1.10 it was experimental.
In the S3 backend configuration block set `use_lockfile = true`; remove or stop adding the `dynamodb_table` argument (it is deprecated in 1.11 and will be removed in a future version).
Ensure the S3 bucket has versioning enabled; Terraform uses S3 conditional writes (`If-None-Match`) to create a `.tflock` file alongside the state file, requiring S3 object conditional write support (available on standard S3 buckets).
The lock file is named `<state-key>.tflock`; ensure the IAM policy for Terraform's identity includes `s3:PutObject`, `s3:GetObject`, and `s3:DeleteObject` on both `*.tfstate` and `*.tflock` object paths.
Test locking by running two simultaneous `terraform plan` operations against the same state; the second should fail with a lock error until the first completes.
For teams migrating from DynamoDB locking, remove the DynamoDB table reference from the backend config and the DynamoDB IAM permissions after verifying native locking works correctly.
Known gotchas
S3 native locking requires the bucket to be in a region that supports S3 conditional writes; all standard AWS regions support this, but GovCloud and some China regions should be verified.
`use_lockfile` is incompatible with `dynamodb_table`; specifying both in the same backend block produces a configuration error.
If a Terraform run is forcibly killed (e.g., SIGKILL or CI runner timeout), the `.tflock` file may remain and must be manually deleted from S3 to unlock the state.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp