Skip to content
hannctl.
PDF ↓
← All work
01 / PF-01 · AWS · IaC IaC automation

AWS multi-region Terraform.

A Terraform module set that builds the same infrastructure in 16 AWS regions from one locals map per region.

PERIOD
Personal project · released Nov 2026
MY ROLE
Design and implementation
TOOLS & CONTEXT
Terraform · AWS · EKS · CloudWatch · AWS Chatbot — 16 regions · 24 modules · 3 examples
16 provider aliases, one assume_roleus-west-2us-west-1us-east-2us-east-1sa-east-1ap-south-1ap-southeast-1ap-southeast-2ap-northeast-3ap-northeast-2ap-northeast-1eu-north-1eu-west-1eu-west-2eu-west-3eu-central-1assume_roleSame role_arn in every region16 regions · 24 modules · one locals map per region
Adding a region means one more locals entry and one more module block.
01 / CONTEXT

Problem

The same resources had to exist in many regions. More regions meant more copied code and a higher risk that regions drift apart.

02 / DECISIONS

Approach

A locals map per region declares the wanted state, and module plus for_each creates it all. Each region has a provider alias that assumes the same role. Terraform cannot choose a provider dynamically inside for_each, so the module block repeats per region.

03 / ENGINEERING

Implementation

  • Terraform
  • AWS
  • EKS
  • CloudWatch
  • AWS Chatbot

Scale · 16 regions · 24 modules · 3 examples

FLOW / 05
16 provider aliases, one assume_roleus-west-2us-west-1us-east-2us-east-1sa-east-1ap-south-1ap-southeast-1ap-southeast-2ap-northeast-3ap-northeast-2ap-northeast-1eu-north-1eu-west-1eu-west-2eu-west-3eu-central-1

Each of the 16 AWS regions gets its own provider alias.

01 / 05
Read every step
  1. Each of the 16 AWS regions gets its own provider alias.
  2. Every alias assumes the same role. The Americas connect first.
  3. Six Asia Pacific regions join through the same role.
  4. Five European regions join, and all 16 regions are on.
  5. Adding a region means one more locals entry and one more module block.
locals map per regionlocals { networks = { seoul = { demo-seoul = { cidr_block = "10.0.0.0/16" subnets = [ ... ] } } }}for_eachVPCcidr_blockSubnetsubnets listSecurity GroupRule map through for_eachEC2 / EKSInstances and node groups per serviceOne more map entry, that many more resources
Keys are stable, so reordering entries recreates nothing.
04 / VERIFICATION

Result

A change is one map entry, and stable keys mean reordering never recreates anything. The 24 modules carry defaults for encryption, IMDSv2, and private S3, and three examples cover networks, EKS, and alerting.

16
Regional provider aliases
24
Terraform modules
3
Validated examples
05 / REFLECTION

What I learned

Stable keys mattered as much as less repetition. count identifies resources by their position in a list, so inserting or reordering an entry can recreate everything after it, while for_each identifies them by map key, so the same resource is addressed whatever the order. Terraform cannot pick a provider inside for_each, and instead of hiding that limit, I repeated the module block per region in plain sight, which turned out easier to read and change. Since then, when the same structure has to exist in many places, I separate data (the map) from code (the module) first, and I judge the design by whether a change ends at one map entry.

OUTCOME

16 regions — 24 modules, one locals map per region

Public repo: pf-01-aws-terraform-multi-region ↗

NEXT / PF-02 · GCP · IaC GCP Terraform GKE platform

Search the site

Quick links ↑ ↓ move · Enter open · Esc close

Choose a theme

Click a badge to switch to that theme on the same content. Dragging only swings it.

Back to the front page →