In a previous article (Terraform Count vs. For Each: Which One Do You Use?), you learned how to create multiple resources using both the for_each
and count
arguments. While these argument made duplicates of entire resources, sometimes you need to repeat blocks within a resource. Enter Terraform dynamic blocks!
In this article, you will learn what are Terraform dynamic blocks and how to add them to your resource definitions. After that, follow a tutorial on how to create multiple subnets in an Azure virtual network.
What are Terraform Dynamic Blocks?
Terraform dynamic blocks are used to create repeatable nested blocks inside an argument. These dynamic blocks represent separate objects that are related or embedded with the containing object. Dynamic blocks are a lot like the for
expression except dynamic blocks iterate over complex values.
For example, let’s say a resource has a setting
block that defines multiple components of a resource. Within the resource definition, use the dynamic
keyword followed by the property name (setting
).
Within the block, use the for_each
argument to provide a complex value for the dynamic block to iterate over. The value in for_each
must be a collection with one element per nested block. Finally, use a nested content
block to define the body of each generated block.
Here is a basic outline of a dynamic block syntax within a resource:
resource "resource_type" "name" {
// Other resource settings
dynamic "setting" {
for_each = var.settings
content {
property1 = setting.value.<property>
// etc.
}
}
}
Creating Multiple Subnets in an Azure Virtual Network
Let’s take a look at an example where you create multiple subnets within an Azure virtual network definition. First, create a local variable of list type that contains multiple objects. Each object represents a subnet’s name and address prefix.
locals {
subnets = [
{
name = "snet01"
address_prefix = "192.168.1.0/24"
},
{
name = "snet02"
address_prefix = "192.168.2.0/24"
}
]
}
Within the virtual network definition, create a dynamic block for the subnet
property that iterates over local.subnets
and accesses the objects in the list using their key name (name
and address_prefix
).
Note that the resource group (azurerm_resource_group.rg
) is defined earlier in the configuration and is not listed in the code below.
resource "azurerm_virtual_network" "vnet" {
name = "vnet-westus2"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
address_space = ["192.168.0.0/16"]
dynamic "subnet" {
for_each = local.subnets
content {
name = subnet.value.name
address_prefix = subnet.value.address_prefix
}
}
}
Performing a terraform plan shows that each subnet is now dynamically generated within the virtual network definition.

Closing
Terraform dynamic blocks are a great way to duplicate properties within a resource. This method saves you from copying and pasting multiple lines of code in your configuration file.
Enjoyed this article? Check out more of my Terraform content here!