TerraformAWS

Managing Multi-Region AWS Infrastructure with Terraform Workspaces

Provision VPCs, RDS clusters and ALBs across us-east-1 and eu-west-1 from a single module, using workspaces for environment isolation.

·9 min read

The Problem with Copy-Paste Infrastructure

Duplicating Terraform code per region creates drift. Instead, use a single reusable module and let workspaces hold per-region state.

Module Structure

infrastructure/
├── modules/
│   └── region/
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
├── environments/
│   ├── us-east-1.tfvars
│   └── eu-west-1.tfvars
└── main.tf

The Root Module

main.tf
terraform {
  backend "s3" {
    bucket         = "my-tfstate"
    key            = "infra/${terraform.workspace}/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
 
module "region_infra" {
  source = "./modules/region"
 
  region      = var.region
  environment = terraform.workspace
  vpc_cidr    = var.vpc_cidr
  db_instance = var.db_instance
}

Switching Between Regions

# Create workspaces
terraform workspace new us-east-1
terraform workspace new eu-west-1
 
# Deploy to us-east-1
terraform workspace select us-east-1
terraform apply -var-file="environments/us-east-1.tfvars"
 
# Deploy to eu-west-1
terraform workspace select eu-west-1
terraform apply -var-file="environments/eu-west-1.tfvars"

Workspaces share the same backend bucket but use different state keys, keeping your state files isolated per region.

RDS with Cross-Region Replica

modules/region/main.tf
resource "aws_db_instance" "primary" {
  count               = var.is_primary ? 1 : 0
  identifier          = "${var.environment}-primary"
  engine              = "postgres"
  engine_version      = "16.1"
  instance_class      = var.db_instance
  allocated_storage   = 100
  storage_encrypted   = true
  multi_az            = true
  deletion_protection = true
}
 
resource "aws_db_instance" "replica" {
  count               = var.is_primary ? 0 : 1
  identifier          = "${var.environment}-replica"
  replicate_source_db = var.primary_db_arn
  instance_class      = var.db_instance
  publicly_accessible = false
}

This pattern lets you promote the replica to primary during a regional failover with a single terraform apply.