Skip to main content
RunBook Academy

← All runbooks in Terraform

medium riskcluster affecting~20 min

Runbook: Migrate the State Backend

1 · Prerequisites

Confirm every item is in place before any state change.

  • A Terraform configuration with a current backend
  • A new backend prepared (bucket, table, credentials)
  • The configuration in Git

2 · Pre-checks

Read-only diagnostic commands. If any of these don't match expected output, stop and investigate further.

  • · The new backend is reachable.
  • · The new backend s credentials are accessible.
  • · The current state is in the source backend.
  • · A maintenance window is approved (for production).

3 · Procedure

Execute each step in order. Verify the expected output of a step before moving to the next.

  1. 1Backup the current state.
  2. 2Update the backend configuration in the configuration.
  3. 3Run terraform init -migrate-state.
  4. 4Verify the state is in the new backend.
  5. 5Verify the plan is empty in the new backend.
  6. 6Update the configuration in Git.
  7. 7Document the migration.

4 · Verification

Confirm the procedure actually fixed the problem.

  • The state is in the new backend.
  • The plan is empty after the migration.
  • The next apply is a no-op.
  • The migration is documented.

5 · Rollback

If verification fails, undo the procedure in reverse order.

  • If the migration fails, re-init with the previous backend configuration.
  • If the state is corrupted, restore from the backup.

6 · Escalation

When the runbook isn't enough, contact:

  • · If the migration fails in production, escalate to the engineering manager.
  • · If the credentials are invalid, escalate to the security team.

Purpose

This runbook walks through the migration of Terraform state from one backend to another. The migration is a managed change with a backup, a migrate-state operation, and a verification.

When to use this runbook

Use this runbook when:

  • Migrating from local state to a remote backend.
  • Migrating between remote backends (e.g. S3 to GCS).
  • Migrating between accounts (e.g. dev to prod).
  • Migrating to a different region.

Procedure

Step 1: Backup the current state

# For local state
cp terraform.tfstate terraform.tfstate.backup-pre-migration

# For remote state
aws s3 cp \
  s3://mycompany-terraform-state/old-path/terraform.tfstate \
  ./terraform.tfstate.backup-pre-migration

The backup is the recovery.

Step 2: Prepare the new backend

For the S3 backend:

# Create the new bucket
aws s3api create-bucket \
  --bucket mycompany-terraform-state-new \
  --region us-east-1

# Enable versioning
aws s3api put-bucket-versioning \
  --bucket mycompany-terraform-state-new \
  --versioning-configuration Status=Enabled

# Create the lock table (if needed)
aws dynamodb create-table \
  --table-name terraform-locks-new \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST

Step 3: Update the backend configuration

Edit versions.tf:

terraform {
  backend "s3" {
    bucket         = "mycompany-terraform-state-new"
    key            = "production/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks-new"
    encrypt        = true
  }
}

Step 4: Run the migration

terraform init -migrate-state

The init:

  • Reads the new backend configuration.
  • Detects the change from the current backend.
  • Copies the state from the current backend to the new backend.
  • Updates the local state to point at the new backend.

The output:

Initializing the backend...
Do you want to migrate the existing state to the new backend?
  Pre-existing state was found while migrating the previous
  default workspace to the newly configured "s3" backend.
  An existing non-empty state already exists in the new backend.
  Do you want to copy the existing state to the new backend?
  Enter "yes" to copy and "no" to start with the existing state.

  Enter a value: yes

Type yes to copy the state.

Step 5: Verify the state

terraform state list

The state has the same resources as before.

terraform state show aws_instance.web

The state has the same attributes.

Step 6: Verify the plan

terraform plan

The plan should be empty.

If the plan is non-empty, the state may have been corrupted or the configuration may have drifted. Investigate.

Step 7: Commit to Git

git add versions.tf
git commit -m "Migrate state backend to new bucket"
git push

Step 8: Document the migration

The migration is documented:

  • The source backend.
  • The destination backend.
  • The migration date.
  • The verification result.

Verification

The runbook is successful if:

  • The state is in the new backend.
  • The plan is empty after the migration.
  • The next apply is a no-op.
  • The migration is documented.

Rollback

If the procedure fails:

  • The migration fails. Re-init with the previous backend configuration.
  • The state is corrupted. Restore from the backup.

Escalation

Escalate to:

  • Engineering manager if the migration fails in production.
  • Security team if the credentials are invalid.
  • Platform team if the backend is unreachable.

References

  1. Backend migration
  2. init -migrate-state