TerraformPilot

Terraform

How to Migrate Terraform State Between Backends

Step-by-step guide to migrate Terraform state between backends. Covers local to S3, S3 to Terraform Cloud, and cross-account migrations safely.

LLuca Berton1 min read

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 plan shows 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

#

Related: How to install AWS CLI on macOS using Homebrew — set up AWS CLI in minutes.

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.

#Terraform#DevOps#Best Practices

Share this article