Skip to content
Latchkey

How to Configure S3 and DynamoDB Remote State in CI

An S3 backend keeps state off the runner, and a DynamoDB lock table serializes runs so two apply jobs cannot write state at once.

Declare an S3 backend block with a DynamoDB dynamodb_table for locking. Authenticate via OIDC and run terraform init to bind the backend in CI.

backend block

main.tf
terraform {
  backend "s3" {
    bucket         = "acme-tf-state"
    key            = "prod/app/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "acme-tf-locks"
    encrypt        = true
  }
}

Init in CI

.github/workflows/ci.yml
steps:
  - uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::111122223333:role/tf-ci
      aws-region: us-east-1
  - run: terraform init -input=false

Gotchas

  • The DynamoDB table needs a primary key named LockID (string) or locking fails.
  • Grant the CI role s3:GetObject/PutObject on the state key plus dynamodb:PutItem/DeleteItem on the lock table.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →