Promotion Without Copy-Paste

Scenario: Trying to be helpful, a team literally copies a working dev state file into the production backend to "promote" the infrastructure - and in doing so accidentally transfers dev's resource identities into what's supposed to be an independent production environment.

The fix for the scenario above starts with a rule worth internalizing precisely: you promote code, never state. Each environment should own its own distinct state file and its own distinct real, provider-side objects from day one - state is not a template to be copied forward, it's a specific record of that one environment's specific resources. What actually moves between environments is an immutable, versioned module or configuration release: a pinned module version (from Module 6) that has been tested and reviewed in one environment gets bumped to that same pinned version in the next environment's own, independent root and state.

A typical pipeline: CI plans and applies a reviewed release against stage first, collects evidence that it worked correctly (successful apply, passing smoke tests), and only then updates prod's pinned module version to match - each environment still applying its own plan against its own state, never touching another environment's state directly. Environment-specific values (a region, an instance size) belong in each environment's own explicit tfvars or root configuration, and policy should govern who's allowed to approve each promotion stage, especially the final one into production.

Analogy: You promote a recipe's version from the test kitchen to the restaurant - "we've settled on this exact recipe, now cook it here too." You do not literally move the test kitchen's own inventory ledger, with its own specific ingredient batches and stock levels, into the restaurant and declare it correct for a completely different kitchen.

A worked configuration

module "service" {
  source  = "app.terraform.io/platform/service/fakecloud"
  version = "4.3.1" # promoted artifact
  env     = "prod"
}

State's own lineage metadata (from Module 5) offers some protection against certain kinds of accidental state-file mix-ups, but process is the real guardrail here, not a technical safety net. Give each environment's backend genuinely separate credentials and a genuinely separate apply identity, with its own approval gate, so that even a badly misconfigured development pipeline has no technical path to reach production's state or infrastructure at all - not just a policy saying it shouldn't.

Common mistakes in production

Goal: Treat the plan as a change contract: understand every create, update, replacement, and destroy before approving it. Reinforce this lesson in the tf-saved-plan-replacement Terraform lab. Open /labs/terraform and choose slug tf-saved-plan-replacement; the lab runs real Terraform against the offline FakeCloud provider.