DEV Community

Mukami
Mukami

Posted on

Getting Started with Multiple Providers in Terraform

How to Deploy Across Multiple AWS Regions Without Losing Your Mind


Day 14 of the 30-Day Terraform Challenge — and today I learned that Terraform isn't limited to one region or one account.

One provider config. Multiple regions. Multiple accounts. Same codebase.

Here's how it works.


What Is a Provider?

A provider is a plugin that translates Terraform code into API calls. The AWS provider knows how to create S3 buckets. The Kubernetes provider knows how to create pods. The random provider generates... random stuff.

When you run terraform init, Terraform downloads these plugins from the Terraform Registry. No manual installation. No hunting for binaries.


Pinning Provider Versions

Never leave your provider version blank. That's how things break unexpectedly.

terraform {
  required_version = ">= 1.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"  # Any 5.x, but not 6.0
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The ~> 5.0 constraint means: use version 5.0 or higher, but less than 6.0. You get bug fixes and security patches, but no breaking changes.

After terraform init, check .terraform.lock.hcl. It records the exact version downloaded. Commit this file to Git. It ensures your whole team uses the same provider version.


The Default Provider

A basic provider config applies to every resource in your configuration:

provider "aws" {
  region = "eu-north-1"
}

resource "aws_s3_bucket" "example" {
  bucket = "my-bucket"  # Deploys in eu-north-1
}
Enter fullscreen mode Exit fullscreen mode

Terraform uses this default provider for every resource that doesn't specify otherwise.


Multiple Regions: Provider Aliases

Want resources in two regions? Define an alias:

# Default provider — primary region
provider "aws" {
  region = "eu-north-1"
}

# Aliased provider — secondary region
provider "aws" {
  alias  = "ireland"
  region = "eu-west-1"
}

# Aliased provider — tertiary region
provider "aws" {
  alias  = "frankfurt"
  region = "eu-central-1"
}
Enter fullscreen mode Exit fullscreen mode

Now you can deploy resources anywhere:

# Uses default provider (eu-north-1)
resource "aws_s3_bucket" "primary" {
  bucket = "primary-bucket"
}

# Uses ireland alias
resource "aws_s3_bucket" "replica" {
  provider = aws.ireland
  bucket   = "replica-bucket"
}

# Uses frankfurt alias
resource "aws_s3_bucket" "backup" {
  provider = aws.frankfurt
  bucket   = "backup-bucket"
}
Enter fullscreen mode Exit fullscreen mode

Terraform knows exactly which API endpoint to call for each resource.


S3 Cross-Region Replication Example

Here's a practical use case: replicate data across regions for disaster recovery.

# Primary bucket in eu-north-1
resource "aws_s3_bucket" "primary" {
  bucket = "app-primary-data"
}

# Replica bucket in eu-west-1
resource "aws_s3_bucket" "replica" {
  provider = aws.ireland
  bucket   = "app-replica-data"
}

# Replication configuration
resource "aws_s3_bucket_replication_configuration" "replication" {
  role   = aws_iam_role.replication.arn
  bucket = aws_s3_bucket.primary.id

  rule {
    id     = "replicate-all"
    status = "Enabled"

    destination {
      bucket        = aws_s3_bucket.replica.arn
      storage_class = "STANDARD"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now every file uploaded to the primary bucket is automatically replicated to Ireland. If eu-north-1 goes down, your data is safe.


Multiple AWS Accounts

For multi-account setups, use assume_role:

provider "aws" {
  alias  = "prod"
  region = "eu-north-1"

  assume_role {
    role_arn = "arn:aws:iam::111111111111:role/TerraformDeployRole"
  }
}

provider "aws" {
  alias  = "staging"
  region = "eu-north-1"

  assume_role {
    role_arn = "arn:aws:iam::222222222222:role/TerraformDeployRole"
  }
}
Enter fullscreen mode Exit fullscreen mode

The IAM role in each account needs permissions to create the resources you're managing. Terraform assumes the role, performs the operations, then drops the credentials.


The Lock File Explained

After terraform init, you get .terraform.lock.hcl:

provider "registry.terraform.io/hashicorp/aws" {
  version     = "5.100.0"      # Exact version installed
  constraints = "~> 5.0"       # Your version constraint
  hashes = [
    "h1:abc123def456...",      # Checksum for verification
  ]
}
Enter fullscreen mode Exit fullscreen mode

Why commit this file?

  • Everyone uses the same provider version
  • No "works on my machine" problems
  • Hashes verify downloads haven't been tampered with

Chapter 7 Learnings

What happens during terraform init?

  1. Reads your required_providers block
  2. Downloads provider binaries from the Terraform Registry
  3. Records exact versions in .terraform.lock.hcl

version vs ~> version:

  • version = "5.0" — exact version only
  • ~> 5.0 — any 5.x version, but not 6.0 (allows patches)

How Terraform chooses a provider: Uses the default provider unless you specify provider = alias in the resource.


What I Learned

Provider aliases unlock multi-region infrastructure. One configuration can now deploy globally.

The lock file is your friend. Commit it. It prevents version drift across your team.

Multi-account deployments are just aliases with assume_role. Same pattern, different accounts.


The Bottom Line

Terraform isn't limited to one region or one account. With provider aliases, you can deploy anywhere.

Need Solution
Multiple regions Provider aliases
Multiple accounts assume_role + aliases
Version consistency Pin versions + commit lock file

One configuration. Global infrastructure.


P.S. The lock file seems like a small detail, but it's saved me from "but it worked on my laptop" conversations more times than I can count. Commit it. 🔒

Top comments (0)