State Locking

Locking stops two applies from running at once and corrupting the shared state file.

Syntaxterraform force-unlock LOCK_ID

State locking ensures that only one Terraform operation writes to the state at a time. Without it, two simultaneous applies could overwrite each other and leave state inconsistent.

How it works with S3 + DynamoDB

Before writing, Terraform puts a lock record in the DynamoDB table. Anyone else who tries to apply sees the lock and waits. When the operation finishes, the lock is released.

If a lock gets stuck

A crashed run can leave a lock behind. As a last resort, terraform force-unlock with the lock ID removes it — only when you are sure no run is active.

Example

Example · bash
# A locked state produces an error like this:
# Error: Error acquiring the state lock
# Lock Info:
#   ID: 9db590f1-9e2c-...
#   Who: alice@soundscode

# Once you are certain nothing is running, remove it:
terraform force-unlock 9db590f1-9e2c-4e3a-b1c2-abcdef123456

When to use it

  • Two CI pipelines trigger at the same time, but DynamoDB locking ensures only one apply proceeds while the other waits, preventing state corruption.
  • A developer tries to run terraform apply while a colleague's apply is in progress and receives a 'state is locked' error with the lock holder's ID, so they wait.
  • An operator uses terraform force-unlock with the lock ID to release a stale lock left behind by a CI pipeline that was killed mid-apply.

More examples

DynamoDB lock table creation

Creates the DynamoDB table that the S3 backend uses for state locking, requiring only a single LockID string attribute.

Example · hcl
resource "aws_dynamodb_table" "tf_lock" {
  name         = "terraform-state-lock"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

S3 backend with locking enabled

References the DynamoDB table in the S3 backend configuration to activate automatic state locking on every operation.

Example · hcl
terraform {
  backend "s3" {
    bucket         = "my-org-terraform-state"
    key            = "prod/app.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-state-lock"  # enables locking
  }
}

Release a stale lock

Shows how to identify a stale lock from the error output and release it with force-unlock using the displayed lock ID.

Example · bash
# See the lock error message
terraform apply
# Error: Error acquiring the state lock
# Lock Info:
#   ID: 12345678-abcd-1234-efgh-000000000000
#   ...CI pipeline killed mid-apply...

# Force-unlock using the ID from the error
terraform force-unlock 12345678-abcd-1234-efgh-000000000000

Discussion

  • Be the first to comment on this lesson.