Terraform Advanced — S3 + DynamoDB Backend
The gold standard for AWS Terraform state: S3 for storage, DynamoDB for locking.
Architecture
┌─────────────────────────────────────────┐
│ terraform apply │
│ ↓ │
│ 1. Acquire lock (DynamoDB) │
│ 2. Read state (S3) │
│ 3. Plan & apply changes │
│ 4. Write updated state (S3) │
│ 5. Release lock (DynamoDB) │
└─────────────────────────────────────────┘
Create the Backend Infrastructure
# bootstrap/main.tf — Run this ONCE with local state
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "terraform_state" {
bucket = "mycompany-terraform-state"
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
}
}
}
resource "aws_s3_bucket_public_access_block" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
Configure the Backend
# terraform.tf
terraform {
backend "s3" {
bucket = "mycompany-terraform-state"
key = "prod/networking/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
State Locking in Action
$ terraform apply
Acquiring state lock. This may take a few moments...
# DynamoDB entry created:
# LockID: "mycompany-terraform-state/prod/networking/terraform.tfstate"
# Info: {"ID":"...","Operation":"OperationTypeApply",...}
# Apply completes...
Releasing state lock. This may take a few moments...
If another engineer runs terraform apply at the same time:
$ terraform apply
Error: Error acquiring the state lock
Lock Info:
ID: abc-123
Path: prod/networking/terraform.tfstate
Operation: OperationTypeApply
Who: alice@laptop
Created: 2025-07-01 10:30:00 UTC
What’s Next?
Encrypt state at rest.