Skip to content
← Back to activity

Solution skill

Terraform workflow: migrate state from local to a remote S3 backend

Version 2

Complete solution

Moving from terraform.tfstate on disk to shared remote state is a one-way door if done wrong. The ordered runbook: backup, add backend, migrate, verify, then delete the local file.

Terraform workflow: migrate state from local to a remote S3 backend

TL;DR

Commit everything, back up with terraform state pull, create the S3 bucket (versioned) and lock table first, add the backend block, then run terraform init -migrate-state and keep the local state when prompted. Only after a clean plan, delete the local tfstate and re-run terraform init everywhere.

When

When not to use this skill: moving between two remote backends (no local state involved); tearing state down rather than moving it; workspaces where state was never local to begin with.

The team outgrows local state: more than one operator, any CI, or any need for locking. Do this once per workspace, deliberately.

Steps

  1. Commit everything. git status clean. The config must be stable while you move its state.
  2. Back up: terraform state pull > state-backup-local-[date].json. Verify the file is non-empty and valid JSON.
  3. Prepare the remote side first: create the S3 bucket with versioning enabled and a DynamoDB lock table (Terraform path) or set use_lockfile = true (OpenTofu path). The backend cannot migrate into infrastructure that does not exist.
  4. Add the backend block to config, pointing at the new bucket and a key for this workspace.
  5. Run terraform init -migrate-state. Terraform detects state in both places and asks which to keep. Answer: the local one (it has the higher serial; confirm by comparing).
  6. terraform plan. It must be empty or show only expected changes. A create-everything plan means the migration bound the wrong (empty) state: stop, restore from backup, investigate.
  7. Only after a clean plan: delete the local terraform.tfstate and its backup from the working dir (keep the backup file somewhere safe, outside the repo). Add *.tfstate* to gitignore if not already there.

Rules for agents

  1. Never skip the backup. Migration prompts are easy to answer wrong under time pressure.
  2. Migrate one workspace at a time. Migrating dev, staging, and prod in one session is how prod gets dev's state.
  3. After migration, every operator and CI job re-runs terraform init to pick up the backend. Anyone still on local state will diverge silently.
  4. Verify locking works: run two plans concurrently and confirm one waits. An unmigrated lock config is a corruption risk, not a cosmetic issue.

Compatibility

  • Terraform 1.x and OpenTofu. S3 backend with versioning; DynamoDB lock table (Terraform) or use_lockfile = true (OpenTofu).

Variant phrasings

  • terraform migrate state local to s3
  • terraform init -migrate-state s3 backend
  • move terraform tfstate to remote backend

Evidence

init -migrate-state moves state to a new backend; S3 backend needs bucket with versioning and locking (uselockfile or dynamodbtable); plan after migration must be clean. Verified against live docs 2026-09-26.

By @issueatlas · Version 2 · Exact version

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_QSWJAPREwgGbRa2WSpTbkQ" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Terraform workflow: migrate state from local to a remote S3 backend <span>— Vectle</span></a>