Free — no signup required

State Fracturing (Layering)

2 min read

The Monolith Problem

Imagine a single Terraform configuration that manages everything: VPC networks, subnets, route tables, RDS databases, S3 buckets, EC2 instances, Lambda functions, and load balancers — all in one directory, all in one state file.

This monolithic approach creates two serious problems:

  1. Slow performance: Every terraform plan must refresh the state of every single resource. With hundreds of resources, this can take 20–30 minutes. Engineers stop running plans frequently, which means they stop catching problems early.
  2. Catastrophic blast radius: A typo in an application server resource could trigger Terraform to evaluate — and potentially modify — your production database. The blast radius of any mistake is the entire company's infrastructure.

The Solution: Layering

The best practice is to fracture your infrastructure into smaller, logical layers, each with its own independent state file, its own directory, and its own deployment lifecycle.

A common three-layer strategy:

Layer Contents Change Frequency
Networking VPCs, Subnets, Route Tables, Transit Gateways Rarely (months)
Data RDS, ElastiCache, S3 Buckets, Kafka Occasionally (weeks)
Application EC2, Lambda, ECS Services, Load Balancers Frequently (daily)

By splitting state this way:
- Changing an application server only requires refreshing the small Application layer state — plans run in seconds, not minutes.
- A mistake in the Application layer cannot touch the Networking layer because they are completely separate state files with separate permissions.
- Different teams can own different layers. The platform team owns Networking; the app team owns Application.

A typical directory structure looks like this:

infrastructure/
├── networking/
│   ├── main.tf
│   ├── outputs.tf
│   └── backend.tf        # key = "networking/terraform.tfstate"
├── data/
│   ├── main.tf
│   ├── outputs.tf
│   └── backend.tf        # key = "data/terraform.tfstate"
└── application/
    ├── main.tf
    ├── outputs.tf
    └── backend.tf        # key = "application/terraform.tfstate"

Key Point: Layering introduces a coordination challenge — layers must be applied in dependency order (Networking first, then Data, then Application). In a CI/CD pipeline, this means separate pipelines per layer, with explicit ordering or manual gates between them. Some teams use tools like Terragrunt to orchestrate this ordering automatically, running apply across layers in the correct sequence with a single command.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free