Managing Terraform State Locking in S3 Without DytnamoDB
Source: Dev.to
Introduction
If you’ve worked with Terraform, you’ve probably followed the standard setup:
- S3 for storing Terraform state
- DynamoDB for state locking
Terraform’s S3 backend now supports state locking without DynamoDB, offering a simpler alternative. This raises an important question: Do you still need DynamoDB for Terraform state locking?
How Terraform State Locking Works
Terraform treats the state file as the single source of truth for your infrastructure. When you run terraform apply, Terraform reads and updates this file. Proper state locking prevents concurrent modifications:
- Terraform attempts to acquire a lock.
- If a lock exists → execution stops.
- If no lock exists → execution proceeds.
- After completion → lock is released.
Locks can be stored as:
- A DynamoDB record (traditional method)
- A
.tflockfile in the S3 bucket (S3‑only method)
When to Use S3‑Only Locking
Suitable Scenarios
- Small teams or solo developers
- Controlled infrastructure changes
- CI/CD pipelines that do not run in parallel
- Desire to reduce cost and infrastructure complexity
Situations to Avoid S3‑Only Locking
- Multiple pipelines running simultaneously (high concurrency)
- Larger engineering teams where concurrent operations are likely
- Critical infrastructure that requires strong consistency guarantees
In these cases, DynamoDB locking remains the safer option.
Common Issues with S3‑Only Locking
If Terraform crashes before releasing the lock, the .tflock file can remain in S3, blocking subsequent runs. Manual cleanup is required:
aws s3 rm s3://your-bucket/path/.tflock
Best Practices for S3 Backend Locking
- Enable S3 versioning to protect the state file.
- Use KMS encryption for data at rest.
- Separate state files per environment (e.g., dev, prod).
- Restrict IAM permissions to the principle of least privilege.
- Monitor state access and changes (e.g., CloudTrail, S3 access logs).
Migrating from DynamoDB to S3‑Only Locking
-
Enable lockfile usage in the backend configuration:
terraform { backend "s3" { bucket = "your-bucket" key = "path/to/terraform.tfstate" region = "us-east-1" encrypt = true kms_key_id = "alias/your-key" use_lockfile = true # Enables S3‑only locking } } -
Migrate the state:
terraform init -migrate-state -
Test concurrency scenarios before adopting the setup in production.
Choosing the Right Approach
- Small team / low concurrency → S3‑only locking is sufficient and reduces cost.
- High‑scale / frequent concurrent deployments → DynamoDB locking provides stronger consistency and reliability.
The key is to match the locking strategy to your workload rather than following defaults blindly.