DEV Community

Mary Mutua
Mary Mutua

Posted on

Getting Started with Multiple Providers in Terraform

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 .tf files
    • building the plan
    • understanding dependencies
    • managing state
  • 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"
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This tells Terraform:

  • use the AWS provider
  • download it from hashicorp/aws
  • allow versions in the 5.x range, but not 6.0 or above

The version constraint:

version = "~> 5.0"
Enter fullscreen mode Exit fullscreen mode

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 init on 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
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

Now I have:

  • a default AWS provider in us-east-1
  • an aliased AWS provider named us_west in us-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"
}
Enter fullscreen mode Exit fullscreen mode

That means:

  • primary goes to the default region
  • replica goes 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"
  }
}
Enter fullscreen mode Exit fullscreen mode

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 init is 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)