Creating Terraform Resources in Multiple Regions

In most terraform modules, resources are created in one region using one provider declaration.

provider "aws" {
  region = "us-west-1"
}

data "aws_region" "primary" {}

resource "aws_ssm_parameter" "param" {
  name  = "/${data.aws_region.primary.name}/param"
  type  = "String"
  value = "notavalue"
}

Sometimes, you need to create resources in multiple regions. Maybe the module has to support disaster recovery to an alternate region. Maybe one of the AWS services you’re using doesn’t support your primary region. When this article was written, Amazon Certificate Manager certificates had to be created in us-east-1 to work with Amazon CloudFront. In cases like these, terraform supports targeting multiple regions.

We recommend using this feature cautiously. Resources should usually be created in the same region. If you’re sure your module should target multiple, here’s how to do it.

  1. Declare a provider for the alternate region. You’ll now have two providers. The original one for your primary region, and the new one for your alternate.
  2. Give the new provider an alias.
  3. Declare resources that reference the new alias in their provider attribute with the format aws.[alias]. This also works for data sources, which is handy for dynamically interpolating region names into resource properties like their name.
provider "aws" {
  alias  = "alternate_region"
  region = "us-west-2"
}

data "aws_region" "alternate" {
  provider = aws.alternate_region
}

resource "aws_ssm_parameter" "alt_param" {
  provider = aws.alternate_region

  name  = "/${data.aws_region.alternate.name}/param"
  type  = "String"
  value = "notavalue"
}

terraform plan doesn’t show what regions it’ll create resources in, so this example interpolates the region name into the resource name to make it visible.

...
Terraform will perform the following actions:

  # aws_ssm_parameter.alt_param will be created
  + resource "aws_ssm_parameter" "alt_param" {
      + arn       = (known after apply)
      + data_type = (known after apply)
      + id        = (known after apply)
      + key_id    = (known after apply)
      + name      = "/us-west-2/param"
      + tags_all  = (known after apply)
      + tier      = "Standard"
      + type      = "String"
      + value     = (sensitive value)
      + version   = (known after apply)
    }
...

To confirm the resources ended up in the right places, here are screenshots of each region’s parameters next to the region drop-down menu in the AWS web console.

We get one in us-west-1 and another in us-west-2, as expected.

Happy automating!

Need more than just this article? We’re available to consult.

You might also want to check out these related articles: