Terraform · Infrastructure as code

How does state locking work and what do you do about stale locks?

MediumlockingconcurrencydynamodbUpdated Oct 2026
Quiz this track

Short answer

State locking prevents two applies from writing the same state concurrently. S3 backends use a lock file or a DynamoDB table, and a stale lock must be investigated before force-unlocking.

Without locking, two runs can read the same state, plan different changes, and overwrite each other. Locking makes the second run wait or fail instead of corrupting the state. The mechanism depends on the backend: DynamoDB items, S3 lock files, blob leases or the HCP Terraform run queue.

hcl
terraform {
  backend "s3" {
    bucket         = "acme-tfstate"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
The DynamoDB table needs a LockID partition key. Terraform 1.10+ can use use_lockfile instead.

Handling a stuck lock

  • Confirm no apply is actually running in CI or on a laptop
  • Check the lock ID and who created it
  • Only then run terraform force-unlock with that ID
  • Add CI concurrency controls so overlapping runs are prevented

A force-unlock is not a rollback. It only removes the lock record, so if another run is still writing state, you can still corrupt it. The safer fix is to stop the other run first and restore state from a versioned copy if needed.

Locking protects state writes, not the cloud APIs. Two different root modules can still race on the same underlying resource if they do not share state.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1What can happen if two applies run without locking?
  2. 2When is force-unlock safe?
  3. 3Does locking prevent two stacks from changing the same resource?
  4. 4How do you prevent overlapping CI runs?

Say it in the interview

State locking stops two runs from writing the same state at once. On S3 I use a native lock file or a DynamoDB table, and the backend waits or fails if a lock exists. If a lock is stuck, I first confirm no apply is still running, then force-unlock that specific ID. I also add CI concurrency groups, because force-unlock only clears the record; it does not make a concurrent write safe.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Terraform mock interview and get scored feedback on depth, clarity and confidence.