When you work across multiple regions or accounts, Terraform expects you to combine the provider block's alias, the resource-level provider meta-argument, and the module's providers map correctly.
The Associate exam frequently tests the distinction between default inheritance, per-resource switching, and module-boundary handoff — along with whether configuration_aliases is declared.
Terraform lets you define multiple configurations for the same provider type. The unnamed configuration is the default; configurations with an alias attribute are aliased configurations. resource and data blocks inherit the default configuration when the provider meta-argument is omitted, and use the corresponding aliased configuration when it is set.
When crossing a module boundary, the root side uses the module block's providers map to explicitly pass provider configurations to the child module. The child module must declare configuration_aliases inside terraform.required_providers to allow the aliases it receives.
Think in three layers: 1) the layer where provider configurations are defined, 2) the layer where each resource picks which configuration to use, and 3) the layer where configurations are passed between modules. Keeping these straight is the shortcut to both stable operations and exam success.
Multi-provider configuration flow (default inheritance and aliased handoff)
Minimal example (default, alias, and per-resource switching)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
provider "aws" {
region = "us-east-1"
}
provider "aws" {
alias = "ue1"
region = "us-east-1"
}
provider "aws" {
alias = "uw2"
region = "us-west-2"
}
resource "aws_s3_bucket" "primary" {
bucket = "example-primary-1234"
}
resource "aws_s3_bucket" "replica" {
bucket = "example-replica-1234"
provider = aws.ue1
}On resource and data blocks, the provider meta-argument explicitly selects the provider configuration. The syntax is provider = <PROVIDER_ADDRESS> (for example aws.ue1) — a configuration reference, not a string.
You can also use a conditional expression to switch between configurations. Every configuration referenced from either side of the conditional must be pre-defined in the same module. Referencing a non-existent configuration produces an error during planning.
Note: the provider meta-argument does not exist on the module block. Pass configurations to modules via the providers map. When you set provider on a resource or data block, the referenced provider configuration must exist in that module.
Example: switching providers via a conditional
variable "primary_region_is_east" {
type = bool
default = true
}
provider "aws" {
region = "us-east-1"
}
provider "aws" {
alias = "uw2"
region = "us-west-2"
}
resource "aws_kms_key" "example" {
description = "Example KMS key"
# Switch between east and west
provider = var.primary_region_is_east ? aws : aws.uw2
}To pass a specific provider configuration (default or alias) to a child module, use the module block's providers map on the root side. The map's keys are provider addresses as seen by the child (aws, aws.replica, etc.) and the values are actual configurations on the root side (aws, aws.ue1, etc.).
On the child module side, declare configuration_aliases on the relevant provider inside terraform.required_providers to explicitly accept the aliases. Without that declaration you'll get a 'module does not declare that alias' error.
Inside the child module, resources can select a received alias such as aws.replica via the provider meta-argument.
Root → child handoff (correct minimal example)
# Root side
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
provider "aws" {
region = "us-east-1"
}
provider "aws" {
alias = "ue1"
region = "us-east-1"
}
module "app" {
source = "./modules/app"
providers = {
aws = aws # Map child's aws to default
aws.replica = aws.ue1 # Map child's aws.replica to the alias
}
}
# Child module (./modules/app)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
configuration_aliases = [ aws.replica ]
}
}
}
resource "aws_iam_role" "main" {
name = "example-app-role"
}
resource "aws_iam_role" "replica" {
name = "example-app-role-replica"
provider = aws.replica
}Multi-region: for multiple regions within the same account, name aliases after the region or role — for example aws.primary, aws.dr, aws.reporting. Set provider explicitly on resources to avoid unintended default inheritance.
Multi-account: separate accounts via assume_role or credential profiles, and give aliases semantic names (prod, stg, ops, etc.). Pass only the necessary combinations to child modules via the providers map to reduce the chance of misuse.
Environment separation: declare provider configurations per environment in the root module and switch via workspaces or variables. When branching on provider with a conditional, pre-define every referenced configuration.
Cross-account assume_role (typical example)
provider "aws" {
region = "us-east-1"
}
provider "aws" {
alias = "ops"
region = "us-east-1"
assume_role {
role_arn = "arn:aws:iam::123456789012:role/ops-admin"
session_name = "tf-ops"
}
}
resource "aws_ssm_parameter" "managed_by_ops" {
name = "/ops/managed"
type = "String"
value = "true"
provider = aws.ops
}Where you make the choice determines its scope and pitfalls. The Associate exam often tests mixing up the terminology and the scope. Here is a summary.
| Mechanism | Where it is set | Scope | Exam-time caveats |
|---|---|---|---|
| Default inheritance | provider block (unnamed) | All resource/data without an explicit provider | Explicit provider is required to use an alias; confirm intent when mixing |
| provider meta-argument | resource/data block | Only that block | Syntax is a reference (aws.alias), not a string; referencing an undefined alias errors out |
| module.providers map | module block (root side) | Entire child module (keys are the child's addresses) | You cannot pass an alias the child does not declare via configuration_aliases |
| configuration_aliases | terraform.required_providers in the child module | Declares which aliases are accepted, not the selection itself | A missing declaration produces a 'provider alias not declared' error |
Common exam trap (missing declaration)
# Root
provider "aws" { region = "us-east-1" }
provider "aws" { alias = "ue1" region = "us-east-1" }
module "bad" {
source = "./modules/bad"
providers = {
aws.replica = aws.ue1 # Want to pass aws.replica to the child
}
}
# Child (./modules/bad) — NG: configuration_aliases not declared
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
# → Typical error: Module does not declare provider alias named "aws.replica".Catch mismatches early via initialization and dependency visualization. In particular, keep verifying that module.providers and configuration_aliases stay aligned.
Use terraform providers to get a bird's-eye view of provider presence and assignments. Run plans in small slices to localize any misconfiguration.
Useful commands
# Initialize
terraform init
# Inspect provider references
terraform providers
# Plan in a narrow scope
terraform plan -target=module.app
terraform plan -target=aws_s3_bucket.replicaAssociate
問題 1
You want to pass both the default aws configuration and the aliased aws.ue1 configuration from the root module to a child module, then create only some resources inside the child module with aws.ue1. Which combination is correct?
正解: A
At a module boundary, you assign actual configurations to the child's provider addresses via the root's module.providers, and the child declares configuration_aliases inside required_providers to accept them. provider must be a reference, not a string. Aliased configurations are not inherited automatically, and you cannot pass a provider via a variable.
Is it possible to skip the default configuration and use only aliased configurations for every resource?
Yes. In that case, you must explicitly set the provider meta-argument on every resource/data block and assign only the required aliases via the providers map when passing them to modules. If even one resource references the default configuration you will get an error, so consistency is critical.
Can the provider meta-argument be assembled dynamically from variables?
Dynamic assembly via string concatenation is not possible. The provider meta-argument is a reference to a provider configuration. You can switch between multiple configuration references with a conditional expression, but every target reference must be pre-defined in the same module.
Is configuration_aliases required even when the child module does not use aliases?
Not required if the child module does not reference an aliased provider internally. If it only receives the default configuration and you omit provider on the resource side, the default is used. If you might use aliases later, declaring configuration_aliases up front makes future extension easier.
Practice with certification-focused question sets
Try free practice questionsNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
HCL Syntax: Terraform's Configuration Language (2026)
HCL2 fundamentals for Terraform — blocks, attributes, expres...
Terraform Authoring & Operations Pro: Complete Guide (2026)
Tactics for the Terraform Pro exam — module authoring, works...
Terraform Providers: Plugin Management Fundamentals (2026)
Provider mechanics — required_providers, versions, mirrors, ...
Terraform Resource Blocks: Declarative Infra Units (2026)
Resource block fundamentals — addresses, references, common ...
Terraform Data Sources: Read-Only External Data (2026)
Data source basics — declaration, refresh behavior, dependen...