Table of Contents
If you are using Terraform with AWS, there is a good chance you have a DynamoDB table that exists for just one reason: state locking.
For most setups, that table sits there quietly, rarely touched, but still needs to be created, secured, and explained to every new engineer who joins the team.
For years, this was simply “how Terraform works”. That changed with Terraform 1.10.
How Terraform State Locking Traditionally Worked
Storing Terraform state in Amazon S3 has been the default choice for a long time. S3 is durable, cheap, and easy to integrate with AWS IAM.
The problem was never state storage: The problem was locking.
S3 does not provide native file locking, which means Terraform needed another system to ensure that two people could not run terraform apply at the same time.
Why DynamoDB Was Introduced
To solve this, Terraform introduced state locking using Amazon DynamoDB.
The common pattern looked like this:
- Terraform state stored in S3
- A DynamoDB table created for locking
- A
LockIDpartition key - Terraform writes a lock record before making changes
- Terraform deletes the record when the run completes
This approach worked reliably and is still widely used today.
The Hidden Cost of DynamoDB Locking
While DynamoDB locking works, it adds more than most teams realize:
- An extra AWS resource to provision
- Additional IAM permissions
- More backend configuration
- Extra documentation for onboarding
In smaller teams especially, the DynamoDB table often provides very little value beyond satisfying Terraform’s locking requirement.
Native S3 State Locking in Terraform 1.10
Terraform 1.10 introduced native S3 state locking, removing the hard dependency on DynamoDB.
Instead of relying on an external database, Terraform now creates a lock file directly in S3, alongside the state file.
How the New Locking Mechanism Works
terraform.tfstate
Terraform will create a lock file:
terraform.tfstate.tflock
- The presence of the
.tflockfile indicates an active lock - Terraform removes the file when the operation finishes
- No DynamoDB table is required
From an operational point of view, this is much easier to reason about.
Enabling Native S3 State Locking
Enabling native S3 locking requires only a single configuration change.
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "terraform.tfstate"
region = "us-east-1"
use_lockfile = true
}
}
That is all that is needed.
There is no table to create, no partition key, and no additional backend resource to manage.
IAM Permissions You Need to Update
Because Terraform now manages a lock file, your S3 permissions must allow Terraform to delete that file.
Make sure the IAM role or user has:
s3:GetObjects3:PutObjects3:DeleteObject
The DeleteObject permission is required because Terraform removes the lock file after the run completes. The state file itself does not need to be deleted, but the lock file does.
Migrating From DynamoDB Locking
If you are already using DynamoDB for locking, there is no urgency to migrate.
A few important points:
- DynamoDB locking is deprecated, not removed
- Existing setups continue to work
- Terraform allows both locking mechanisms to exist at the same time
A safe migration approach looks like this:
- Enable
use_lockfile = true - Keep the DynamoDB table temporarily
- Validate Terraform runs
- Remove DynamoDB when comfortable
This avoids unnecessary risk, especially in production environments.
Why Native S3 Locking Makes Sense
This change is not just about saving DynamoDB costs.
In practice, native S3 locking means:
- Fewer AWS resources
- Simpler backend configuration
- Cleaner IAM policies
- Easier onboarding for new engineers
For new Terraform backends, it is increasingly difficult to justify adding DynamoDB purely for locking.
When Should You Use This?
- New Terraform setups should use native S3 locking by default
- Existing environments can migrate gradually
- Large Terraform estates benefit from reduced complexity
There are still edge cases where DynamoDB may make sense, but for most teams, native S3 locking is enough.
Conclusion
Terraform 1.10 quietly removed one of the long-standing annoyances of AWS backends.
State locking no longer requires DynamoDB.
The backend is simpler.
The operational surface area is smaller.
If you are setting up Terraform today, native S3 state locking should be your default choice — and DynamoDB can finally be optional.