for_each in HashiCorp Terraform can be used to create more advanced Terraform configurations that are able to deploy multiple instances of a resource or module with similar or slightly different configurations. In this article, we will explore how to use the for_each loop in Terraform with basic code examples. The examples are targeting resource types within the azurerm Terraform provider, but the same code can be used in Terraform regardless of provider and type needed.
Let’s get started!
Table of Contents
What is for_each in Terraform?
for_each is a loop function in HashiCorp Terraform that allows you to create multiple instances of a resource with varying attributes. Unlike count, which creates multiple instances of a resource with identical attributes, for_each creates instances with unique attribute values. This feature allows you to define your resources more precisely and accurately.
The syntax for using for_each looks as follows:
resource <PROVIDER_TYPE> "<NAME>" {
for_each = <COLLECTION>
# resource config here
}
The <PROVIDER_TYPE> and <NAME> for the resource block will remain the same as with any other resource configuration is defined in Terraform code. The difference is adding the for_each and passing it a collection. The collection will be looped over with each item in the set or map being a new instance of the resource that will be configured. The collection can be coded inline or as a local or var value that is passed to it.
Within the resource configuration, Terraform will use the same configuration for every resource that is configured as it loops through the collection passed as a set or map to the for_each. When looping through the collection, the item in the collection is accessed through the each keyword. The each keyword has a key and value parameter that can be used to access the key and value of the item in the collection.
Using Terraform for_each with a set
A set is a way to define a collection of items to pass to for_each for configuring multiple resource instances. If a list is used in the code, then the toset() function can be used to convert it to a set. This may be required as lists are not supported directly when using for_each.
This method of passing a set to for_each can be used to configure both resource and module blocks in Terraform, as follows.
Use for_each on a resource block
The following is a simple example of using a set to define the items for the for_each set on a resource block. This example defines a list of Azure Resource Group names, then uses the toset() function to convert the list to a set so that for_each can be used to iterate over them and configure the resources.
resource azurerm_resource_group "resource_groups" {
for_each = toset([
"prod-b59-webapp1-rg",
"prod-b59-database1-rg"
])
name = each.key
location = "eastus"
}
This example provisions multiple Azure Resource Groups (via the azurerm_resource_group type) by passing a set of strings defining the resource group names. When doing this, there is only a value on the each object that is used to access each item in the collection. So, for this, only the each.key is used to access the string value of the items in the collection.
Use for_each on a module block
The method of passing a set to the for_each parameter can also be used to configure the usage of Terraform module blocks as well.
The following is a simple example of using a set to define the items for the for_each set on a module block. This example defines a list of names to use, converting the list of a set using the toset() function, so multiple instances of the module can be configured accordingly.
module "resource_groups" {
for_each = toset([
"prod-b59-webapp1",
"prod-b59-database1"
])
source = "./resource_groups_module"
name = "${each.key}-rg"
}
The name parameter of the module is configured using the each.key to access the item value from the list. Notice, an expression is used to append a string to the key as it configures the value of the name parameter. This is just showing that an expression can optionally be used with each.key if necessary.
Using Terraform for_each with a map
A map is a way to define a collection of key-value pairs in Terraform. The keys and values of the map can be of any data type.
The following is a simple map definition of the locals.resource_groups variable with items that can be used to define Azure Resource Groups with the name as the key and the location as the value:
locals {
resource_groups = {
"prod-b59-webapp1-rg" = "eastus"
"prod-b50-database1-rg" = "eastus"
}
}
Using the previous map definition, the following is an example of using a for_each to configure Azure Resource Groups using this map:
resource azurerm_resource_group "resource_groups" {
for_each = local.resource_groups
name = each.key
location = each.value
}
In this example, for_each is being used to configure multiple Azure Resource Groups (using the azurerm_resource_group resource type) as defined by the locals.resource_groups variable.
When using for_each, the each keyword is used to access the specific item in the collection as it’s looped over. In this example, the name parameter is being set to the key of the item in the collection using each.key. The location parameter is being set to the value of the item in the collection using the each.value.
Using Terraform for_each with a map of Objects
Let’s take a look at a similar example to the previous use of a map with the for_each to define the list of resources to configure but with a map of objets this time. Instead of simple key-value pairs, we’ll use a map that has a key of type string with the value being an object that can contain one or more values itself. This can be used to set up more complex configurations using for_each.
The following is and example definition of a locals.virtual_machines variable with some configurations defined using a map of objects to declare the Azure Virtual Machines to configure.
locals {
virtual_machines = {
"prod-b59-vm1" = {
location = "eastus"
size = "Standard_B2s"
}
"prod-b59-vm2" = {
location = "westus"
size = "Standard_B4ms"
}
}
}
Using the previous map of objects definition, the following is an example of using a for_each to configure Azure Virtual Machines using this map:
resource azurerm_virtual_machine "vm" {
for_each = local.virtual_machines
name = each.key
location = each.value.location
vm_size = each.value.size
# other VM configurations here
}
This example used the each.key for setting the name parameter of the azurerm_virtual_machine resource, and with the each.value to access the object it was able to access the location and size properties to set the location and vm_size parameters of the azurerm_virtual_machine resource.
Advantages of using for_each in Terraform
Using the Terraform for_each has several advantages over using other loop functions such as count:
- Simplifies Resource Management
Withfor_each, you can manage multiple resources of the same type with a single block of code. This is useful when you have a several resources to manage that are similarly configured, and it reduces the amount of code you need to write and maintain. - Avoids Repetitive Code
Without usingfor_each, multipleresourceand/ormoduleblocks would be needed. This would result in repeating the same code multiple times, and would violate the DRY (Don’t Repeat Yourself) practice of writing clean code. Withfor_each, you can create multiple resources with the same or similar configuration in a single block, which can help to simplify your code. - Provides Granular Control
Withfor_each, the creation of multiple resources with unique attributes more easily as compared to usecountinstead. This provides more granular control over the configuration of resources performed using thefor_eachloop function instead ofcount. - Increases Efficiency
Configuring multiple resources or modules with the same or similar settings can be time-consuming and error prone due to user error. The use offor_eachsimplifies this process by reducing the amount of code written that would otherwise end up being copied and pasted. This helps improve quality and decrease coding time when appropriate.
Using for_each in HashiCorp Terraform provides several advantages that make it easier to manage your infrastructure. It simplifies resource management, avoids repetitive code making code more DRY, provides granular control, and increases efficiency. These benefits make for_each a valuable tool for configuring resources and modules in Terraform, especially when working with large infrastructures.
Original Article Source: Terraform: Use for_each to deploy multiple resources written by Chris Pietschmann (If you're reading this somewhere other than Build5Nines.com, it was republished without permission.)

Microsoft Azure Regions: Interactive Map of Global Datacenters
Create Azure Architecture Diagrams with Microsoft Visio
Unlock GitHub Copilot’s Full Potential: Why Every Repo Needs an AGENTS.md File
IPv4 Address CIDR Range Reference and Calculator
Configuring GitHub Actions to Run Jobs on Specific Branches




