IBM Support

How to Configure count or for_each with Terraform Modules

How To


Steps

Introduction

According to the Terraform Style Guide, "The for_each and count meta-arguments let you create multiple resources from a single resource block depending on run-time conditions. You can use these meta-arguments to make your code flexible and reduce duplicate resource blocks. If the resources are almost identical, use count. If some of arguments need distinct values that you cannot derive from an integer, use for_each."

Using these meta-arguments with a resource block is straightforward. An example of using these meta-arguments with resources is available in the Terraform count versus for_each article. This guide explains how to use count and for_each with modules.

Use Case

You can configure count or for_each to create multiple instances of an entire module. The following example demonstrates the syntax for each and highlights the difference in how Terraform addresses the resulting resources in the state file. Understanding this difference is important, especially when refactoring code from count to for_each or vice versa, as it requires state manipulation.

Procedure

Example Configuration

This example uses the following file structure.

$ tree
.
├── main.tf
└── module
    └── src.tf

Create the main.tf file with module blocks that use count and for_each.

## ./main.tf

# COUNT
module "using_count" {
  source = "./module"
  count  = 2
  name   = "test-${count.index}"
}

# FOR_EACH
variable "project" {
  type = map(any)
  default = {
    a = {
      some_num = 2,
      env      = "dev"
    },
    b = {
      some_num = 1,
      env      = "stage"
    }
  }
}

module "using_foreach" {
  source   = "./module"
  for_each = var.project
  name     = "test-${each.key}-${each.value.env}"
}

Create the module/src.tf file with a resource that the modules will create.

## ./module/src.tf

variable "name" {}

resource "random_pet" "r" {
  prefix = var.name
}

Applying the Configuration

  1. Initialize the Terraform configuration to download providers and configure the modules.

    $ terraform init
  2. Review the execution plan. Terraform will plan to create five resources (two modules, two random_pet resources, and one null resource from the random_pet provider).

    $ terraform plan

    The output shows the plan.

    Plan: 5 to add, 0 to change, 0 to destroy.
  3. Apply the configuration to create the resources. Note the different resource addresses in the output. The module using count references resources with a numeric index, while the module using for_each references them with the map key.

    $ terraform apply
    • count address example: module.using_count[0].random_pet.r
    • for_each address example: module.using_foreach["a"].random_pet.r

Refactoring from count to for_each

If you need to refactor a module that uses count to use for_each, you must perform state surgery because the resource addresses are different. In the example above, the name argument for the random_pet resource is also generated differently, which would cause the resource to be replaced.

To refactor safely, follow these steps.

  1. Create backups of your configuration files and the terraform.tfstate file.
  2. Update your Terraform configuration to use the new for_each syntax.
  3. Remove the old resources from the state file using the terraform state rm command or a removed block.
  4. Import the existing resources back into state with their new addresses using the terraform import command or an import block.

Additional Information

Document Location

Worldwide

[{"Type":"MASTER","Line of Business":{"code":"LOB77","label":"Automation Platform"},"Business Unit":{"code":"BU048","label":"IBM Software"},"Product":{"code":"SSGH5YK","label":"IBM Terraform Self-Managed"},"ARM Category":[{"code":"","label":""}],"ARM Case Number":"","Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"All Version(s)"}]

Historical Number

32048299945747

Document Information

Modified date:
16 March 2026

UID

ibm17265598