Day 14 of my Terraform journey was about understanding one of the most important Terraform building blocks: providers.
Until now, most of my Terraform configurations had only used one provider configuration at a time. That was enough for simple examples, but real infrastructure often spans:
- multiple AWS regions
- multiple AWS accounts
- and sometimes multiple cloud platforms
Today I learned how Terraform providers actually work under the hood, how Terraform installs and pins them, and how provider aliases make multi-region and multi-account setups possible.
GitHub reference:
π Github Link
What Is a Provider in Terraform?
A provider is a plugin that Terraform uses to communicate with an external platform such as AWS, Azure, or Google Cloud.
A simple way to think about it is this:
- Terraform Core handles:
- reading your
.tffiles - building the plan
- understanding dependencies
- managing state
- reading your
- the provider handles:
- the real API calls to AWS or another platform
So when I declare something like:
resource "aws_s3_bucket" "example" {
bucket = "my-example-bucket"
}
Terraform Core understands the structure of the resource, but the AWS provider is the part that actually knows how to call AWS and create that bucket.
That was one of the biggest mindset shifts for me today: providers are not just configuration details. They are what connect Terraform to the outside world.
How Terraform Installs Providers
Terraform installs providers when you run:
terraform init
During initialization, Terraform reads the required_providers block and downloads the provider binaries from the Terraform Registry.
A production-friendly pattern looks like this:
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
This tells Terraform:
- use the AWS provider
- download it from
hashicorp/aws - allow versions in the
5.xrange, but not6.0or above
The version constraint:
version = "~> 5.0"
means:
- use any version
>= 5.0 - but
< 6.0
That helps avoid unexpected breaking changes from a future major version.
Why Provider Version Pinning Matters
This was one of the clearest best-practice lessons from today.
If provider versions are not controlled:
-
terraform initon a different machine may install a different provider version - that can cause unexpected plan changes
- or even break a working configuration
Pinning provider versions makes the setup more stable and repeatable.
In other words:
- no version pinning = more surprises
- version pinning = more predictability
What .terraform.lock.hcl Does
After running terraform init, Terraform creates:
.terraform.lock.hcl
This file records the exact provider versions Terraform selected.
For example, in my Day 14 lab it recorded:
- the provider source
- the exact provider version
- the version constraints
- package hashes used to verify the provider binaries
This matters because it keeps provider installation consistent across:
- my machine
- teammatesβ machines
- CI/CD systems
That is why .terraform.lock.hcl should be committed to version control.
It does not store secrets.
It stores dependency lock information.
That was an important clarification for me.
Using a Single Provider
A simple provider configuration looks like this:
provider "aws" {
region = "us-east-1"
}
This means:
- AWS is the provider
- resources without any explicit override will use
us-east-1
That default provider configuration applies automatically to all AWS resources in the configuration unless told otherwise.
Working with Multiple Copies of the Same Provider
The most practical concept I learned today was provider aliases.
If I want Terraform to deploy some resources in one region and other resources in another region, I need multiple configurations of the same provider.
Here is the pattern:
provider "aws" {
region = "us-east-1"
}
provider "aws" {
alias = "us_west"
region = "us-west-2"
}
Now I have:
- a default AWS provider in
us-east-1 - an aliased AWS provider named
us_westinus-west-2
Any resource that should use the secondary region must reference that aliased provider explicitly.
Example:
resource "aws_s3_bucket" "primary" {
bucket = "my-app-primary-bucket"
}
resource "aws_s3_bucket" "replica" {
provider = aws.us_west
bucket = "my-app-replica-bucket"
}
That means:
-
primarygoes to the default region -
replicagoes to the aliased provider region
My Multi-Region Day 14 Lab
For the hands-on part, I built a multi-region AWS example using provider aliases.
The lab included:
- a primary S3 bucket in
us-east-1 - a replica S3 bucket in
us-west-2 - IAM resources for replication
- an S3 replication configuration between the two buckets
That gave me a practical example of how multiple provider configurations can work together in one Terraform project.
This was much more useful than just reading about aliases in theory.
Multi-Account Pattern with assume_role
I also reviewed the multi-account pattern.
For multiple AWS accounts, Terraform can use aliased providers with assume_role:
provider "aws" {
region = "us-east-1"
alias = "production"
assume_role {
role_arn = "arn:aws:iam::111111111111:role/TerraformDeployRole"
}
}
provider "aws" {
region = "us-east-1"
alias = "staging"
assume_role {
role_arn = "arn:aws:iam::222222222222:role/TerraformDeployRole"
}
}
I did not apply this part live because I do not yet have multiple AWS account roles set up, but I documented the configuration pattern as part of the lesson.
The important idea is that aliases are not only for regions.
They are also for:
- multiple accounts
- different access contexts
- more advanced module usage later on
My Main Takeaway
Day 14 made Terraform providers feel much less magical.
Before today, I mostly saw providers as something you add near the top of a file and then move on.
Now I understand that providers control:
- which platform Terraform talks to
- where infrastructure gets deployed
- which account or region is used
- which provider version is installed
- how multi-region and multi-account architectures become possible
The biggest lessons for me were:
- always pin provider versions
- always understand what
terraform initis doing - commit
.terraform.lock.hcl - use aliases carefully when working across regions or accounts
That is the foundation for more advanced provider and module work coming next.
Full Code
GitHub reference:
π Github Link
Follow My Journey
This is Day 14 of my 30-Day Terraform Challenge.
See you on Day 15 π
Top comments (0)