Andrew Loutfi

[SAMPLE] Draw your Terraform state boundaries before they draw themselves

Andrew Loutfi · · 2 min read


This is a sample post shipped with the site scaffold so the typography can be checked against real-shaped content. Delete it before launch.

Nobody plans a 4,000-resource Terraform state. It accretes: the network module lands next to the database because that's where the file was open, someone adds DNS "temporarily," and eighteen months later a plan takes eleven minutes and touching a tag forces a full-stack review.

State is a blast radius, not a folder

Every resource in a state file shares fate with every other resource in it. A bad refactor, a provider bug, a mistyped terraform state rm — the damage is scoped to the file. That makes the state boundary the most important architectural decision in an IaC codebase, and it's usually made by accident.

Three questions locate a sane boundary:

  1. Change cadence — does this change weekly or yearly? Networking and DNS move slowly; application infrastructure moves constantly. Separate them.
  2. Failure tolerance — if this state were corrupted, what's the recovery story? Keep hard-to-rebuild things (stateful stores, zones) away from things you'd happily recreate.
  3. Ownership — can one team apply this without paging another? If not, the file is a meeting disguised as infrastructure.

A shape that survives growth

StateContentsCadence
foundationVPCs, subnets, DNS zonesquarterly
platformclusters, registries, shared queuesmonthly
app-<name>one service's infra, one per servicedaily

Cross-state references go through data sources or remote state reads, and the dependency arrow only points down the table — apps read platform outputs, never the reverse:

data "terraform_remote_state" "platform" {
  backend = "s3"
 
  config = {
    bucket = "acme-tfstate"
    key    = "platform/terraform.tfstate"
    region = "us-east-1"
  }
}
 
resource "aws_ecs_service" "api" {
  name    = "api"
  cluster = data.terraform_remote_state.platform.outputs.cluster_arn
}

The migration nobody wants

Splitting a monolithic state is terraform state mv drudgery, but it's mechanical and it's reversible. The longer version of this post would cover moved blocks and how to stage the split behind CI. The short version: do it while the plan still finishes in single-digit minutes, because the cost only compounds.