Separate Terraform state by account, region, and blast radius; use S3 lockfiles, versioning, and safer refactors. Read the full cheat sheet.

Partition State by Account, Region, and Blast Radius

Terraform state is not a single shared notebook for the whole estate. At multi-region scale, one remote backend for everything turns a routine apply into a cross-team outage risk. Split state so each unit owns a clear boundary: AWS account (or equivalent), region, and blast radius. Account boundaries keep credentials and change ownership aligned with who can destroy what. Region boundaries keep latency and data residency obvious and stop a mis-targeted plan from reading or writing objects in the wrong geography. Blast-radius boundaries go further—separate networking, identity, shared data planes, and product workloads so a bad apply in one layer cannot rewrite another.

A practical pattern is one state per deployable unit that you would restore or roll back together. Shared modules stay in code; shared live infrastructure gets its own state only when many consumers depend on it. Prefer many small states over a few giant ones. Large states slow plans, widen lock contention, and make reviews harder because every change looks global.

Name backends and key prefixes so operators can map a workspace to account, region, and purpose without opening the console. Document ownership in the same place you document how to plan and apply. When a team cannot name the state file that holds their resources, the partition is already wrong.

Remote Backends: S3, Lockfiles, and Versioning

Use a remote backend with durable object storage and a locking mechanism. S3-style backends pair well with lockfiles (or a dedicated lock table, depending on your setup) so two applies cannot write the same state at once. Locking is not optional in multi-region or multi-team environments: concurrent applies corrupt state or produce silent drift that only shows up on the next plan.

Turn on object versioning on the state bucket. Versioning is the safety net when a bad apply or a partial write lands. You need a known-good prior state object, not a hope that someone still has a local copy. Restrict who can list, read, and delete versions; deletion of old versions should be deliberate and rare. Encrypt at rest, block public access, and limit write access to the pipelines and roles that actually run Terraform. Treat the state bucket like a production database of infrastructure truth.

  • One backend config per state unit; avoid “default” keys that several stacks share by accident.
  • Always enable locking before the first multi-operator apply.
  • Keep versioning on; test that you can restore a previous state object in a non-prod account.
  • Log access to state objects where your platform allows it; state leaks equal secret and topology leaks.

Safer Refactors Without Breaking the Live Map

Refactors fail when code moves but state does not. Prefer moved blocks (or equivalent state moves) over destroy-and-recreate when renaming modules or resources. Plan first; read the plan for destroys you did not intend. If you must split one state into several, migrate resources deliberately: import or move into the new state, remove from the old, and verify both plans are clean before deleting anything. Never hand-edit state JSON in production paths unless you have no other option and a restore plan ready.

Keep environments (dev, staging, prod) in separate states and preferably separate accounts. Multi-region means multi-backend key, not one key with region tags sprinkled in. Run plans against the exact state you will apply. When blast radius is high—identity, DNS, shared networking—require smaller change sets, stricter review, and longer soak than for app-only stacks. Scale comes from clear ownership of each state file, locks that actually hold, versioned history you can restore, and refactors that update the map of real resources instead of hoping the next apply will figure it out.

Automate Your Content with AI Video Generator

Try it Free →