The provider block declares and configures a Pulumi provider for your stack. It supports version constraints, named aliases for multi-region or multi-account deployments, and per-resource routing via the provider meta-argument.
provider {} currently emits Pulumi Python provider instantiation code. When the native UBX engine (UBX-159) becomes the default backend, provider configuration will map to that engine’s provider model instead.
Syntax
Default provider
provider aws {
region = "us-east-1"
version = ">= 6.0.0"
}
aws — bare identifier naming the provider type (not a quoted string)
version — optional semver constraint string; warn-only on unrecognized format
- All other fields are forwarded to the Pulumi provider constructor
Aliased provider
provider aws prod_eu {
region = "eu-west-1"
version = ">= 6.0.0"
}
The second bare identifier (prod_eu) is the alias. Aliases allow multiple instances of the same provider type to coexist. XCL identifiers use underscores, not hyphens — prod_eu not prod-eu.
Multiple providers
Same type, different regions
provider aws {
region = "us-east-1"
}
provider aws prod_eu {
region = "eu-west-1"
}
Both providers are in scope simultaneously. Resources with no provider meta-arg use the default (unaliased) provider implicitly at deploy time.
Multiple provider types
provider aws {
region = "us-east-1"
version = ">= 6.0.0"
}
provider kubernetes {
host = @cluster.endpoint
}
provider datadog {
api_url = "https://api.datadoghq.eu"
}
Each provider type generates a separate import pulumi_<type> as <type> statement and pulumi-<type> entry in requirements.txt.
Per-resource routing
Use the provider meta-argument inside a resource body to direct that resource to a specific provider instance:
provider aws {
region = "us-east-1"
}
provider aws prod_eu {
region = "eu-west-1"
}
stack "multi-region" {
// Uses the default (us-east-1) provider — no meta-arg needed.
us_bucket = aws_s3_bucket {
bucket = "assets-us"
}
// Explicitly routes to the prod_eu alias.
eu_bucket = aws_s3_bucket {
provider = aws.prod_eu
bucket = "assets-eu"
}
}
provider = aws.prod_eu references the provider by name.alias. For the default (unaliased) provider use provider = aws.
The provider meta-argument is accepted on:
name = TypePath { } resource declarations
name = module { } module calls
name = deploy helm|kustomize|manifest { } deploy declarations
name = sync argocd|flux { } sync declarations
name = data type { } data source bindings
version field
provider aws {
version = ">= 6.0.0"
}
The version field accepts any semver constraint string. Recognized operators: >=, <=, >, <, !=, ==, ~>, ^, ~. Unrecognized formats produce a warning (not a hard error) — the program still compiles.
The version is translated into a pip specifier in requirements.txt:
XCL version | requirements.txt entry |
|---|
>= 6.0.0 | pulumi-aws>=6.0.0 |
~> 6.1 | pulumi-aws~=6.1 |
< 7.0.0 | pulumi-aws<7.0.0 |
| (absent) | pulumi-aws>=1.0.0 |
When no version is present, the fallback >=1.0.0 is emitted.
Generated Python
Provider instantiation
provider aws {
region = "us-east-1"
}
Generates a # ── Providers ── section before data bindings and resources:
# ── Providers ─────────────────────────────────────────────────────────────────
aws_provider = aws.Provider("aws",
region="us-east-1",
)
Aliased provider
provider aws prod_eu {
region = "eu-west-1"
}
Generates:
aws_prod_eu_provider = aws.Provider("prod_eu",
region="eu-west-1",
)
The Python variable name is derived as {name}_provider or {name}_{alias}_provider.
Per-resource opts
eu_bucket = aws_s3_bucket {
provider = aws.prod_eu
bucket = "assets-eu"
}
Generates:
eu_bucket = aws.s3.BucketV2("eu_bucket",
bucket="assets-eu",
opts=pulumi.ResourceOptions(provider=aws_prod_eu_provider),
)
opts=pulumi.ResourceOptions(provider=...) is appended after all regular properties.
Provider → Python package mapping
| Provider type | Python module alias | pip package |
|---|
aws | aws | pulumi-aws |
kubernetes | kubernetes | pulumi-kubernetes |
datadog | datadog | pulumi-datadog |
gcp | gcp | pulumi-gcp |
azure / azure-native | azure_native | pulumi-azure-native |
| (other) | {name} | pulumi-{name} |
The correct import pulumi_{name} as {name} statement is emitted even when no provider {} block is declared — imports are derived from resource type paths. A provider {} block adds the provider to the import list explicitly and enables version pinning.
Error conditions
Duplicate default provider
provider "aws" is declared more than once — use an alias for multiple instances: provider aws prod { ... }
Two provider aws { } blocks without aliases produce a hard compile error.
Duplicate alias
provider "aws" alias "prod_eu" is declared more than once
Two provider aws prod_eu { } blocks with the same name and alias produce a hard compile error.
Undeclared provider reference
provider "aws.missing" is not declared — add: provider aws { ... }
Using provider = aws.missing inside a resource body when no provider aws missing { } block exists is a hard compile error.
provider "aws" version ">= 6.0.0" may not be a valid semver constraint — expected e.g. ">= 6.0.0"
A version value that doesn’t start with a recognized operator or digit produces a warning. The program still compiles.
Scope rules
provider {} blocks are top-level — they live outside any stack {} and are visible to all stacks in the compilation unit
- Two providers can have the same
name if they have different aliases
- Provider keys in scope are
"aws" (default) and "aws.prod_eu" (aliased)
- The
provider = aws.prod_eu meta-argument is validated at compile time — the referenced provider must be declared