Table of Contents
Introduction
Migrating Terraform state between backends is a common operation as teams evolve their infrastructure management practices. Whether moving from local state to S3, or from S3 to Terraform Cloud, this guide covers the process safely.
Prerequisites
- Terraform installed (v1.0+)
- Access to both source and destination backends
- No pending changes (
terraform planshows no changes) - Backup of current state
Migration 1 - Local to S3
Step 1 - Backup Current State
cp terraform.tfstate terraform.tfstate.backup
Step 2 - Create S3 Backend Resources
resource "aws_s3_bucket" "terraform_state" {
bucket = "my-terraform-state-bucket"
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
Step 3 - Add Backend Configuration
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "production/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
Step 4 - Initialize with Migration
terraform init -migrate-state
Terraform will ask:
Do you want to copy existing state to the new backend?
Enter a value: yes
Step 5 - Verify
terraform plan
# Should show: No changes. Your infrastructure matches the configuration.
Migration 2 - S3 to Terraform Cloud
Step 1 - Create Terraform Cloud Workspace
Configure your Terraform Cloud organization and workspace.
Step 2 - Update Backend
terraform {
cloud {
organization = "my-org"
workspaces {
name = "production"
}
}
}
Step 3 - Migrate
terraform init -migrate-state
Migration 3 - Cross-Account S3
Step 1 - Pull State
terraform state pull > state.json
Step 2 - Update Backend Config
terraform {
backend "s3" {
bucket = "new-account-state-bucket"
key = "production/terraform.tfstate"
region = "us-east-1"
role_arn = "arn:aws:iam::ACCOUNT_ID::role/TerraformStateAccess"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
Step 3 - Initialize and Migrate
terraform init -migrate-state
Safety Checklist
Before any migration:
- Run
terraform plan— confirm no pending changes - Backup state file locally
- Ensure new backend is accessible
- Test with a non-production workspace first
- Verify state after migration with
terraform plan - Remove old state from source after confirming
Common Errors
Backend configuration changed
Error: Backend configuration changed
Run terraform init -reconfigure to reinitialize with the new backend.
State lock error during migration
terraform force-unlock LOCK_ID
Hands-On Courses
Conclusion
State migration is straightforward when done carefully. Always backup first, verify after, and test with non-production environments. The terraform init -migrate-state command handles most scenarios automatically.

