Stage 4 · Provision
Terraform at Scale
Remote State Architecture
Backend layout, state locking, state data boundaries, and blast-radius reduction — designing state for large organizations.
State Boundaries
State boundaries define what resources live in the same state file. The right boundaries prevent a single terraform apply from affecting unrelated resources. Wrong boundaries create cross-state dependencies that are difficult to manage.
| Boundary Strategy | Pros | Cons |
|---|---|---|
| All resources in one state | Simple | Massive blast radius, slow plan/apply |
| Per-environment state | Isolation between environments | Cross-environment dependencies |
| Per-component state | Small blast radius | Many state files to manage |
| Per-team state | Team autonomy | Cross-team dependencies |
Backend Layout
A backend layout organizes state files across buckets, prefixes, and containers. The layout should reflect your organizational structure, access patterns, and blast radius requirements.
# S3 bucket structure
s3://my-terraform-state/
networking/
vpc/terraform.tfstate
subnets/terraform.tfstate
firewalls/terraform.tfstate
compute/
eks/terraform.tfstate
ec2/terraform.tfstate
database/
rds/terraform.tfstate
redis/terraform.tfstate
shared/
dns/terraform.tfstate
iam/terraform.tfstateEach component has its own state file. The VPC state does not affect the EKS state. Changes to networking can be reviewed and applied independently. The shared directory holds resources used by multiple components.
# networking/vpc/backend.tf
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "networking/vpc/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
# compute/eks/backend.tf
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "compute/eks/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}Each backend points to a different state file in the same bucket. The DynamoDB table provides locking across all state files. The encrypt flag ensures all state files are encrypted at rest.
State Locking
State locking prevents concurrent modifications to the same state file. Most remote backends support locking natively. Without locking, concurrent applies corrupt the state file.
# DynamoDB table for state locking
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
# Backend with DynamoDB locking
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "networking/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}DynamoDB uses conditional writes for locking. When Terraform acquires a lock, it creates a DynamoDB item with a condition. Another process cannot acquire the lock until the item is deleted. PAY_PER_REQUEST avoids capacity planning.
Cross-State References
When resources in one state file need values from another state file, use terraform_remote_state or data sources. This creates a dependency between state files without coupling them.
# In compute/eks/main.tf
data "terraform_remote_state" "networking" {
backend = "s3"
config = {
bucket = "my-terraform-state"
key = "networking/vpc/terraform.tfstate"
region = "us-east-1"
}
}
module "eks" {
source = "../../modules/eks"
vpc_id = data.terraform_remote_state.networking.outputs.vpc_id
subnet_ids = data.terraform_remote_state.networking.outputs.private_subnet_ids
}terraform_remote_state reads outputs from another state file. The dependency is explicit — changes to the networking state may affect the EKS state. This is the primary mechanism for cross-state data sharing.
Blast Radius Reduction
- Split state by component — networking, compute, database, shared.
- Use smaller state files — faster plan/apply, less risk per change.
- Separate shared resources — DNS, IAM, and certificates in their own state.
- Use workspaces or directories per environment — dev drift does not affect prod.
- Implement approval workflows — manual approval for production state changes.
State Encryption
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "networking/terraform.tfstate"
region = "us-east-1"
encrypt = true # Server-side encryption
kms_key_id = "arn:aws:kms:us-east-1:123456789:key/abc-def"
dynamodb_table = "terraform-locks"
}
}The encrypt flag enables server-side encryption for the state file. The kms_key_id specifies a custom KMS key for encryption. Without encrypt = true, state files are stored in plaintext in S3.
Keep backend configuration in a separate file and pass sensitive values at init time. This allows different environments to use different backends without code changes.
Terraform state files contain sensitive values in plaintext — database passwords, API keys, and certificates. Treat state files with the same security as production credentials. Enable encryption and restrict access.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.