Module 9, Remote State and Team Workflows
Why Remote State
Local state works for solo learning. The moment a second person runs terraform apply, you have a conflict. Remote state stores terraform.tfstate in S3 so the team shares one source of truth. DynamoDB adds locking so only one apply runs at a time.
S3 Backend Configuration
terraform {
backend "s3" {
bucket = "my-company-terraform-state"
key = "finpay/production/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
Bootstrap, Create the Backend (One Time Only)
# bootstrap/main.tf, run this ONCE manually before everything else
resource "aws_s3_bucket" "terraform_state" {
bucket = "my-company-terraform-state"
}
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration { status = "Enabled" }
}
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-state-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute { name = "LockID"; type = "S" }
}
warning
This bootstrap bucket cannot be managed by Terraform itself (chicken-and-egg). Create it manually or with a separate bootstrap workspace.
How Locking Works
1. You run terraform apply
2. Terraform writes a lock record to DynamoDB (LockID = state file path)
3. Colleague tries to apply → Terraform sees the lock → immediately errors
4. Your apply finishes → Terraform deletes the lock
5. Colleague can now apply
If apply crashes with lock stuck:
terraform force-unlock LOCK_ID
State Versioning
S3 versioning on the state bucket means:
- Every apply creates a new version of
terraform.tfstate - You can roll back to any previous state if something goes wrong
- Accidental state file deletion is recoverable
- Full audit trail of every infrastructure change
This is non-negotiable in production.
Sharing State Between Configs
Use terraform_remote_state to read outputs from another config:
data "terraform_remote_state" "networking" {
backend = "s3"
config = {
bucket = "my-company-terraform-state"
key = "finpay/networking/terraform.tfstate"
region = "us-east-1"
}
}
resource "aws_instance" "app" {
subnet_id = data.terraform_remote_state.networking.outputs.private_subnet_id
}
Knowledge Check
- Why is local state insufficient for team use?
- What does the DynamoDB table provide in the S3 backend?
- What is the bootstrap problem and how do you solve it?
- What happens if
terraform applycrashes mid-run with a lock in place? - Why should versioning be enabled on the S3 state bucket?
- How do you share outputs between two separate Terraform configurations?