Skip to main content
RunBook Academy

TerraformXV · Environment Architecture and State BoundariesArchitecture

State Boundaries: Decomposing the Terraform Estate

Intermediate⏱ ~12 minbashterraform

What you'll learn

  • Design state boundaries for production
  • Decompose by lifecycle, ownership, environment, and failure domain
  • Avoid the failure modes of fragmented and monolithic states
  • Recognise when more or fewer states are appropriate

Prerequisites

Verified against Terraform CLI 1.9.x · OpenTofu 1.7.x · HCL 2.0 · bpg/proxmox provider 0.66+ · hashicorp/local provider 2.5+ · hashicorp/null provider 3.2+ · hashicorp/random provider 3.6+ · hashicorp/http provider 3.4+ · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · 2026-08-12

Not yet marked complete on this device.

A state boundary is the unit of failure. A failure in one state cannot affect another state. The state boundary is the primary control for blast radius. This lesson teaches how to design state boundaries for production Terraform estates.

When to split a state

A state should be split when:

  • Lifecycles differ. Network resources change rarely; compute resources change often. The two have different deployment cadences.
  • Ownership differs. The network team owns the network; the application team owns the compute. The two teams will make changes independently.
  • Failure domains differ. A failure in the network should not affect the compute. The two have different failure domains.
  • Environments differ. Production and non-production are different. The two have different testing requirements.
  • Security boundaries differ. IAM and security are higher-trust than compute. The two have different security requirements.

A state should not be split when:

  • The resources are tightly coupled. A subnet and its route table are tightly coupled; they should be in the same state.
  • The operational complexity is not worth it. Three resources with one operator do not need three states.
  • The blast radius is already small. A state with three resources that are not critical has a small blast radius.

The decomposition framework

A production estate is decomposed by:

AxisExamples
LifecycleNetwork (changes rarely), Compute (changes often), Database (changes occasionally)
OwnershipPlatform team, Application team, Security team
Failure domainNetwork availability zone, Compute cluster, Database cluster
EnvironmentProduction, staging, dev
SecurityInternet-facing, internal, restricted

The axes are not exclusive. A production state is decomposed along multiple axes:

prod-network-001          # production network (changes rarely)
prod-compute-001          # production compute (changes often)
prod-database-001         # production database (changes occasionally)
prod-shared-001           # production shared services (IAM, secrets)
staging-network-001
staging-compute-001
...

Each state has a clear ownership and a clear deployment cadence.

The state boundary trade-off

There is a trade-off between blast radius and operational complexity:

One state containing all infrastructure
  - Blast radius: the entire estate
  - Operational complexity: 1 state, 1 plan, 1 apply

Many states, one per resource
  - Blast radius: 1 resource
  - Operational complexity: 1000 states, 1000 plans, 1000 applies

The trade-off is real. The right answer is in the middle.

The right answer is:

  • One state per lifecycle.
  • One state per ownership.
  • One state per environment.

These axes give a manageable number of states with manageable blast radii.

The pattern

A production estate can be decomposed like:

states/
├── network/
│   ├── main.tf
│   ├── variables.tf
│   ├── outputs.tf
│   └── versions.tf
├── compute/
│   ├── main.tf
│   ├── variables.tf
│   ├── outputs.tf
│   └── versions.tf
├── database/
│   ├── main.tf
│   ├── variables.tf
│   ├── outputs.tf
│   └── versions.tf
└── shared/
    ├── main.tf
    ├── variables.tf
    ├── outputs.tf
    └── versions.tf

Each state has its own:

  • Backend configuration.
  • Lockfile.
  • Output values.

The states communicate via terraform_remote_state data sources.

The cross-state coupling

The states are coupled. The compute state depends on the network state:

# compute/main.tf
data "terraform_remote_state" "network" {
  backend = "s3"
  config = {
    bucket = "mycompany-terraform-state"
    key    = "network/terraform.tfstate"
    region = "us-east-1"
  }
}

resource "aws_instance" "web" {
  ami = "ami-0e1bed4f"
  subnet_id = data.terraform_remote_state.network.outputs.public_subnet_id
}

The coupling is explicit. The compute state cannot be applied without the network state being applied first.

The deployment cadence

Each state has a deployment cadence:

StateCadence
NetworkQuarterly
ComputeDaily
DatabaseMonthly
SharedAs needed

The cadence is the rhythm of change. The state boundaries are the deployment boundaries.

The state boundary failures

The failure modes of state boundaries:

Too monolithic. A single state containing all infrastructure has the blast radius of the entire estate.

Too fragmented. A state per resource creates operational complexity that is not worth the marginal blast radius reduction.

Wrong coupling. A state boundary that puts tightly coupled resources in different states creates a deployment ordering problem.

No outputs. A state that does not expose its outputs cannot be consumed by other states.

Wrong environment. A state containing both production and non-production resources has the wrong blast radius.

The composition test

For a state boundary proposal, answer:

  • What is the lifecycle of the resources?
  • What is the ownership of the resources?
  • What is the failure domain of the resources?
  • What is the environment of the resources?
  • What is the security boundary of the resources?

If the answers are consistent, the state boundary is correct. If the answers are mixed, the state boundary is wrong.

What comes next

The next lesson is workspaces — the Terraform feature for multiple states in a single backend configuration.

Verification

Knowledge check · 7 questions

  1. Q1. Why are multiple environments important?

  2. Q2. What is a state boundary?

  3. Q3. Workspaces are appropriate for production isolation.

  4. Q4. What is the role of directories in multi-environment estates?

  5. Q5. Which of the following are good production patterns for environments? (Select all that apply.)

  6. Q6. What is the role of accounts/projects/subscriptions in environments?

  7. Q7. A team uses workspaces for staging and production. The state is corrupted in staging. Production is unaffected. What is the fix?

Passing score: 75%. Answers are checked in this browser.