Terraform Provider Aliases

A company with offices in two cities keeps a separate phone line in each one. A call to the New York office goes through the New York line, and a call to London goes through the London line. Terraform providers behave like those phone lines. One provider block connects to one region or one account. A project that spans two regions or two accounts needs a second line. Provider aliases supply it.

The Problem: One Provider, One Region

A plain provider block sets a single region.

provider "aws" {
  region = "us-east-1"
}

Every resource now lands in us-east-1. A backup bucket in us-west-2 has no way to reach another region through this block.

Creating an Alias

Add a second provider block with an alias argument. The block without an alias becomes the default. The block with an alias stays available on request.

provider "aws" {
  region = "us-east-1"
}

provider "aws" {
  alias  = "west"
  region = "us-west-2"
}

Diagram: Two Lines, Two Regions

                 +-------------------+
                 |  Terraform config |
                 +---------+---------+
                           |
          +----------------+----------------+
          |                                 |
 provider "aws"                  provider "aws" alias "west"
 region us-east-1                region us-west-2
          |                                 |
          v                                 v
 +-----------------+               +-----------------+
 | Primary bucket  |               | Backup bucket   |
 +-----------------+               +-----------------+

Choosing a Provider for a Resource

A resource without a provider argument uses the default provider. Add the argument to pick the alias. The reference format is PROVIDER.ALIAS.

resource "aws_s3_bucket" "primary" {
  bucket = "shop-primary-2026"
}

resource "aws_s3_bucket" "backup" {
  provider = aws.west
  bucket   = "shop-backup-2026"
}

Terraform creates the first bucket in us-east-1 and the second in us-west-2 during the same run.

Data Sources Accept Aliases Too

data "aws_availability_zones" "west" {
  provider = aws.west
  state    = "available"
}

Passing Aliases to Modules

A module uses the default provider unless the caller says otherwise. The providers argument passes a specific provider into the module.

module "backup_network" {
  source = "./modules/network"

  providers = {
    aws = aws.west
  }
}

Inside the module, the code refers to a plain aws provider. The caller decides which real connection hides behind that name.

Modules That Need Two Providers

A module that works across two regions declares the extra provider name in its own required_providers block.

terraform {
  required_providers {
    aws = {
      source                = "hashicorp/aws"
      configuration_aliases = [aws.replica]
    }
  }
}

The caller then passes both connections.

module "database" {
  source = "./modules/database"

  providers = {
    aws         = aws
    aws.replica = aws.west
  }
}

Common Uses for Aliases

Use CaseExample
Multi-region setupPrimary app in one region and backups in another
Multiple accountsA shared logging account beside a workload account
Global servicesA certificate that must live in a specific region
Disaster recoveryA standby copy in a distant region

Multiple Accounts With Roles

provider "aws" {
  region = "us-east-1"
}

provider "aws" {
  alias  = "logging"
  region = "us-east-1"

  assume_role {
    role_arn = "arn:aws:iam::210987654321:role/TerraformLoggingRole"
  }
}

Resources tagged with provider = aws.logging land in the logging account while the rest stay in the default account.

Limits to Remember

  • Terraform needs every provider reference to be a fixed name. A variable cannot choose an alias.
  • The for_each argument cannot select providers dynamically.
  • Many aliases make files harder to read. Group related resources into modules and pass one alias per module.

Key Points

  • One provider block connects to one region or account.
  • The alias argument creates an extra named connection.
  • Resources pick an alias with provider = aws.west.
  • Modules receive aliases through the providers map.
  • Modules that need several connections declare configuration_aliases.
  • Alias names must be fixed text, not variables.