Terraform forbids using for_each and count on provider configurations, forcing multi-region setups to be written manually one by one. This episode covers OpenTofu's exclusive feature: dynamic provider iteration that loads many provider instances at once for concise multi-region and multi-account architectures.

In the previous episode 6 we covered OpenTofu's first exclusive feature: native client-side state encryption — how the state file is encrypted on the client side before being sent to the remote backend, complete with AWS KMS and PBKDF2 key providers. Now that our most valuable asset is secure, we turn to the second practical problem that gives IaC engineers headaches: handling many regions and many cloud accounts.
Imagine your company rolls out an app to three AWS regions at once — Singapore for Southeast Asia, Virginia for the Americas, and Frankfurt for Europe. In classic Terraform, you'd have to write the provider "aws" block three times manually, or go through modules so the provider can be looped. Both approaches are tedious, repetitive, and prone to typos.
In this episode we cover OpenTofu's second exclusive feature: dynamic provider iteration — the ability to load many provider instances dynamically using for_each. You'll see how concise managing multi-region and multi-account becomes in HCL once this feature exists.
In Terraform, meta-arguments like count and for_each work on resources, data sources, and modules — but they're forbidden on the provider block. Provider configuration is the only block that can't be looped.
As a consequence, for three regions you write:
provider "aws" {
alias = "singapore"
region = "ap-southeast-1"
}
provider "aws" {
alias = "virginia"
region = "us-east-1"
}
provider "aws" {
alias = "frankfurt"
region = "eu-central-1"
}Note the alias keyword — each provider instance needs a unique name so resources can reference it through the provider argument. Now imagine 10 regions, or 5 accounts times 5 regions: the blocks explode into dozens of tedious copies to write and maintain. Terraform's "official" solution is wrapping everything in a module called with for_each — elegant, but it still adds a layer of complexity.
OpenTofu removes that restriction. Provider blocks can now use for_each (and count) exactly like resources, with each.key and each.value available inside:
provider "aws" {
alias = each.key
region = each.value
} for_each = {
singapore = "ap-southeast-1"
virginia = "us-east-1"
frankfurt = "eu-central-1"
}One block replaces three. Adding a new region is just adding one line to the for_each map — no more copy-pasting provider blocks.
Note
With for_each, each.key is the map key and each.value is its value. In the example above, the key becomes the provider alias and the value becomes the region — so resources can call aws.singapore, aws.virginia, and so on.
Resources still select which provider to use through the provider argument:
resource "aws_vpc" "singapore" {
provider = aws.singapore
cidr_block = "10.0.0.0/16"
}The real power shows when spreading across many accounts. Imagine running the same resource in the dev and prod accounts, each with a different role to assume:
provider "aws" {
alias = each.key
region = each.value.region
assume_role {
role_arn = "arn:aws:iam::${each.value.account_id}:role/DeployRole"
}
} for_each = {
dev = { account_id = "111122223333", region = "ap-southeast-1" }
prod = { account_id = "444455556666", region = "us-east-1" }
}With a two-line map, OpenTofu loads two providers with different credentials for two accounts. Combine this pattern with for_each on resources and modules, and one map containing your entire environment layout drives everything else. This is the pattern that keeps "big workspaces" tidy.
Warning
Make sure every provider instance has a unique alias — use each.key to make it automatic. Without an alias, OpenTofu refuses to load multiple providers of the same type. Also, don't use for_each for truly identical provider configurations; use this feature to capture variation across regions or accounts.
tofu init — per-account credentials are resolved at apply time, not init time.provider blocks can be refactored into this iteration form without changing any resources — the same alias keeps resources valid.tofu validate after refactoring, then review the changes with tofu plan before applying.Summary of episode 7:
count and for_each on provider blocks, forcing manual writing per region or account.for_each and count on providers, complete with each.key and each.value.assume_role yields providers isolated per account.alias remains required so resources can reference provider instances.The ability to load many providers dynamically opens the way to writing far more DRY infrastructure. In the next episode, episode 8, we'll cover Advanced Expressions, Built-in Functions & Loops — diving into OpenTofu's built-in functions, the count, for_each, and depends_on meta-arguments, lifecycle rules, and for expressions and ternary operators for writing expressive HCL. See you there!