DEV Community

Yash
Yash

Posted on

Terraform remote state for multi-account AWS: complete setup

Terraform remote state for multi-account AWS: complete setup

Local state is a trap. Two engineers run apply simultaneously and state diverges. Here's the complete remote state setup.

Architecture

S3 Bucket (management account)
  project-alpha/prod/terraform.tfstate
  project-alpha/staging/terraform.tfstate

DynamoDB Table: terraform-state-locks (LockID key)
Enter fullscreen mode Exit fullscreen mode

Bootstrap (run once per management account)

resource "aws_s3_bucket" "state" {
  bucket = "my-org-terraform-state-${data.aws_caller_identity.current.account_id}"
}
resource "aws_s3_bucket_versioning" "state" {
  bucket = aws_s3_bucket.state.id
  versioning_configuration { status = "Enabled" }
}
resource "aws_s3_bucket_server_side_encryption_configuration" "state" {
  bucket = aws_s3_bucket.state.id
  rule { apply_server_side_encryption_by_default { sse_algorithm = "AES256" } }
}
resource "aws_s3_bucket_public_access_block" "state" {
  bucket = aws_s3_bucket.state.id
  block_public_acls = true; block_public_policy = true
  ignore_public_acls = true; restrict_public_buckets = true
}
resource "aws_dynamodb_table" "locks" {
  name = "terraform-state-locks"; billing_mode = "PAY_PER_REQUEST"; hash_key = "LockID"
  attribute { name = "LockID"; type = "S" }
  point_in_time_recovery { enabled = true }
}
Enter fullscreen mode Exit fullscreen mode

Backend configuration per project

terraform {
  backend "s3" {
    bucket         = "my-org-terraform-state-111111111111"
    key            = "project-alpha/prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-state-locks"
    encrypt        = true
    role_arn       = "arn:aws:iam::111111111111:role/terraform-state-access"
  }
}
Enter fullscreen mode Exit fullscreen mode

Common pitfalls

  • Key collisions: Use <project>/<environment>/terraform.tfstate consistently
  • Forgetting encrypt = true: Bucket encryption alone doesn't protect in-transit operations
  • Lock table region mismatch: DynamoDB must be in the same region as S3
  • No versioning: State corruption happens — versioning is your rollback

Step2Dev provisions a remote state backend automatically for every new project.

👉 step2dev.com

Top comments (0)