Goodbye DynamoDB — Terraform S3 Backend Now Supports Native Locking
Terraform’s S3 backend now includes S3 native state locking as an opt-in experimental feature. This new locking mechanism can work independently or alongside a DynamoDB lock. When both are enabled, Terraform must successfully acquire a lock from both sources before proceeding with any operations.
Why S3 Native State Locking?
Terraform relied on DynamoDB-based locking to prevent state file conflicts when multiple users or automation processes accessed it. While effective, this approach required maintaining an extra AWS resource (a DynamoDB table) — which added cost and complexity.
With S3 native state locking, Terraform introduces a built-in locking mechanism that works without DynamoDB. You can still use it alongside DynamoDB for redundancy, but once fully transitioned, you’ll no longer need to manage a separate lock table.
How to Enable S3 Locking
First of all, make sure that your terraform version is 1.9.0 or greater. To enable S3 native state locking, simply set use_lockfile
to true
in your backend configuration:
Before: Using DynamoDB for Locking
terraform {
backend "s3" {
bucket = "your-terraform-state-bucket"
key = "path/to/your/statefile.tfstate"
region = "us-east-1"
dynamodb_table = "your-dynamodb-lock-table" # Current state lock
encrypt = true
}
}
After: Switching to S3 Native Locking
terraform {
backend "s3" {
bucket = "your-terraform-state-bucket"
key = "path/to/your/statefile.tfstate"
region = "us-east-1"
encrypt = true
use_lockfile = true #S3 native locking
}
}
How It Works
With S3 locking enabled, Terraform creates a lock file in the same location as the state file. This lock file shares the same name as the state file but has a .tflock
extension. Depending on your setup, you may need to update S3 bucket policies and IAM permissions to accommodate the new lock file:
Here is the code if you want to give it a try:
terraform {
backend "s3" {
bucket = "state-bucket-2025"
key = "dev/terraform.tfstate"
region = "us-east-1"
encrypt = true
use_lockfile = true #S3 native locking
}
}
variable "region" {
type = string
default = "eastus"
}
resource "aws_instance" "example_instance" {
ami = "ami-12345678"
instance_type = "t3.micro"
tags = {
Name = "ExampleInstance-${var.region}"
}
}
Future Updates
In an upcoming minor version of Terraform, the use_lockfile
attribute will graduate from experimental to fully supported. At that point, attributes related to DynamoDB-based locking will be deprecated.
Follow me on Linkedin!