Ravindra BagaleCourses & study guides मराठी Track your progress

Guides

How to Store Terraform State in S3 with DynamoDB Locking

Create a versioned S3 bucket and a DynamoDB lock table, add a backend "s3" block, run terraform init -migrate-state, and keep IAM private.

Friends, state is the map of what cloud already has. Chala mitrano — put it in S3 with a DynamoDB lock before two people apply.

Quick answer

Hold this vertical picture:

  1. Create versioned S3 bucket.
  2. Create DynamoDB lock table.
  3. Add backend block.
  4. init -migrate-state.
  5. plan; protect IAM; gitignore state.

Language: English · मराठी · हिंदी

Local tf filesCode in Git S3 state objectShared truth DynamoDB lockOne apply at a time terraform initBackend wired plan / applySafe team use
Remote state path

Why remote state

Laptop state cannot lock or share safely.

Why: Two applies on local files corrupt reality. What: S3 object + DynamoDB lock. How: backend block then migrate.

Example 1: Local state problem

Type this:

mkdir -p /tmp/tfstate && printf '%s\n' 'terraform {' '  # local state file appears after init/apply' '}' > /tmp/tfstate/main.tf && printf '%s\n' 'ok: laptop terraform.tfstate is easy to lose and hard to lock'

You will see:

ok: laptop terraform.tfstate is easy to lose and hard to lock

What it means: Teams at Infosys ban laptop-only state for shared envs.

Example 2: S3 bucket sketch (names are examples)

Type this:

printf '%s\n' 'aws s3api create-bucket --bucket company-tfstate-dev-ap-south-1 --region ap-south-1 --create-bucket-configuration LocationConstraint=ap-south-1'

You will see:

aws s3api create-bucket --bucket company-tfstate-dev-ap-south-1 --region ap-south-1 --create-bucket-configuration LocationConstraint=ap-south-1

What it means: One bucket (or prefix) per account; enable versioning next.

Example 3: Enable versioning

Type this:

printf '%s\n' 'aws s3api put-bucket-versioning --bucket company-tfstate-dev-ap-south-1 --versioning-configuration Status=Enabled'

You will see:

aws s3api put-bucket-versioning --bucket company-tfstate-dev-ap-south-1 --versioning-configuration Status=Enabled

What it means: Versioning saves you after a bad apply.

Concept 1: Bucket and lock table

Versioning + LockID table.

Why: No lock means colliding applies. What: create-bucket; create-table LockID. How: encrypt = true in backend.

Example 4: DynamoDB lock table

Type this:

printf '%s\n' 'aws dynamodb create-table --table-name company-tf-locks --attribute-definitions AttributeName=LockID,AttributeType=S --key-schema AttributeName=LockID,KeyType=HASH --billing-mode PAY_PER_REQUEST'

You will see:

aws dynamodb create-table --table-name company-tf-locks --attribute-definitions AttributeName=LockID,AttributeType=S --key-schema AttributeName=LockID,KeyType=HASH --billing-mode PAY_PER_REQUEST

What it means: LockID is the required hash key name Terraform expects.

Example 5: Backend block

Type this:

printf '%s\n' 'terraform {' '  backend "s3" {' '    bucket         = "company-tfstate-dev-ap-south-1"' '    key            = "network/terraform.tfstate"' '    region         = "ap-south-1"' '    dynamodb_table = "company-tf-locks"' '    encrypt        = true' '  }' '}' > /tmp/tfstate/backend.tf && cat /tmp/tfstate/backend.tf

You will see:

terraform {

What it means: encrypt + lock table — Capgemini audit baseline.

Example 6: Migrate init

Type this:

printf '%s\n' 'terraform init -migrate-state'

You will see:

terraform init -migrate-state

What it means: Moves local state into S3 when you answer yes.

Concept 2: Init and plan

Migrate once; then plan reads remote.

Why: Skipping migrate leaves two truths. What: init -migrate-state; plan. How: Respect lock errors.

Example 7: Plan against remote

Type this:

printf '%s\n' 'terraform plan'

You will see:

terraform plan

What it means: Plan reads the remote state; two laptops now share truth.

Example 8: Lock contention message

Type this:

printf '%s\n' 'Error acquiring the state lock — someone else is applying'

You will see:

Error acquiring the state lock — someone else is applying

What it means: Wait or ask the owner; force-unlock only with a ticket.

Example 9: Who can read state

Type this:

printf '%s\n' 'State may hold secrets — lock S3 IAM to the CI role and platform team'

You will see:

State may hold secrets — lock S3 IAM to the CI role and platform team

What it means: Never make the state bucket public.

Concept 3: Security and layout

State may contain secrets.

Why: Public buckets and committed state fail audits. What: Tight IAM; key per stack; gitignore. How: state list to verify.

Example 10: Key layout

Type this:

printf '%s\n' 'key = env/app/terraform.tfstate   # e.g. prod/payments/terraform.tfstate'

You will see:

key = env/app/terraform.tfstate   # e.g. prod/payments/terraform.tfstate

What it means: One key per stack keeps blast radius small.

Example 11: Verify backend

Type this:

printf '%s\n' 'terraform state list'

You will see:

terraform state list

What it means: Lists resources from the remote file after init.

Example 12: Never commit state

Type this:

printf '%s\n' '.gitignore must include terraform.tfstate and .terraform/'

You will see:

.gitignore must include terraform.tfstate and .terraform/

What it means: Amazon/Flipkart reviews reject committed state files.

Remote state card

1 S3 bucket + versioning 2 DynamoDB LockID table 3 backend "s3" block 4 init -migrate-state 5 IAM private 6 never commit tfstate

Suppose: Error acquiring lock

Wait; force-unlock only with approval.

Suppose: AccessDenied on S3

CI role needs s3 and dynamodb permissions.

Ravindra Bagale's Tip

At Infosys, interviewers ask why DynamoDB: answer — Terraform writes a lock item so a second apply waits instead of corrupting state.

Check yourself (quiz)

Q1. Why S3?

Shared durable state object

Q2. Why DynamoDB?

Lock so applies do not collide

Q3. Migrate command?

terraform init -migrate-state

Q4. Public bucket?

Never

Q5. Lock error?

Wait or approved force-unlock

Q6. Commit tfstate?

No — gitignore it

Reading tracking

Mark this guide when you finish. Your browser remembers it on this device.

bucket → lock table → backend → migrate → plan. Did you understand? Let us try it once more.

Frequently asked questions

Why not Git for state?

State changes constantly and may hold secrets.

Force-unlock?

Only when sure no apply runs.

One bucket many keys?

Yes — key per stack.

encrypt true?

SSE on the object.

Workspaces vs keys?

Keys (or folders) are clearer for many teams.

CI permissions?

s3 + dynamodb on that bucket/table.