What if you could write your cloud setup once and have Terraform fill in all the repeated details perfectly every time?
Dynamic blocks vs for_each decision in Terraform - When to Use Which
Imagine you need to create many similar parts in your cloud setup, like multiple firewall rules or repeated resource settings. Doing this by copying and pasting code for each part feels like writing the same email over and over again.
Manually repeating code is slow and easy to mess up. If you want to change something, you must update every copy, risking mistakes and wasting time. It's like juggling many balls and dropping some.
Using dynamic blocks and for_each in Terraform lets you write the repeated parts just once. Terraform then automatically creates all the needed pieces based on your list or map. This saves time, reduces errors, and keeps your setup neat.
resource "aws_security_group" "example" { ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } }
resource "aws_security_group" "example" { dynamic "ingress" { for_each = [80, 443] content { from_port = ingress.value to_port = ingress.value protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } } }
You can easily create many similar cloud settings by changing just your input list, making your infrastructure flexible and error-free.
When setting up a web server, you might want to open ports 80 and 443 for HTTP and HTTPS. Instead of writing two blocks, you use dynamic blocks or for_each to generate both automatically.
Manual repetition is slow and risky.
Dynamic blocks and for_each automate repeated parts.
This leads to cleaner, safer, and easier-to-change cloud setups.
Practice
Solution
Step 1: Understand nested block repetition
Dynamic blocks are designed to repeat nested blocks inside a single resource.Step 2: Compare with for_each usage
for_each repeats entire resources or top-level blocks, not nested blocks.Final Answer:
Dynamic blocks -> Option AQuick Check:
Nested block repetition = Dynamic blocks [OK]
- Using for_each to repeat nested blocks inside one resource
- Confusing count with dynamic blocks
- Trying to use locals for repeating blocks
setting?Solution
Step 1: Identify correct dynamic block syntax
Dynamic blocks use the syntax: dynamic "block_name" { for_each = ... content { ... } }.Step 2: Check other options for syntax errors
Options A, B, and C misuse for_each, count, or locals incorrectly for nested blocks.Final Answer:
dynamic "setting" { for_each = var.settings; content { key = each.value } } -> Option DQuick Check:
Correct dynamic block syntax = dynamic "setting" { for_each = var.settings; content { key = each.value } } [OK]
- Placing for_each directly inside resource without dynamic
- Using count for nested blocks
- Trying to assign locals directly as blocks
aws_security_group_rule resources created?
resource "aws_security_group_rule" "example" {
for_each = { for idx, port in var.ports : idx => port }
type = "ingress"
from_port = each.value
to_port = each.value
protocol = "tcp"
security_group_id = var.sg_id
}
Assuming var.ports = [80, 443].Solution
Step 1: Understand for_each on resource
for_each creates one resource instance per map or set element. Here, var.ports has 2 elements.Step 2: Count resource instances
Since var.ports has 2 ports, Terraform creates 2 aws_security_group_rule resources, one for each port.Final Answer:
2 resources -> Option BQuick Check:
for_each with 2 items = 2 resources [OK]
- Thinking for_each creates one resource regardless of items
- Confusing dynamic blocks with resource repetition
- Assuming ports combine into one resource
resource "aws_instance" "example" {
for_each = var.instances
ami = "ami-123456"
instance_type = "t2.micro"
dynamic "ebs_block_device" {
for_each = each.value.ebs_volumes
content {
device_name = ebs_block_device.value.device_name
volume_size = ebs_block_device.value.size
}
}
}
Assuming var.instances is a map with nested ebs_volumes lists.Solution
Step 1: Identify the error in dynamic block reference
Inside the content block of a dynamic block, the iterator must be referenced aseach.value, notebs_block_device.value. The iterator variable is alwayseachregardless of the dynamic block name.Step 2: Confirm the fix
Change todevice_name = each.value.device_nameandvolume_size = each.value.size. Other options are incorrect: dynamic blocks work inside resources, for_each works on resources, count is not required.Final Answer:
Incorrect reference to dynamic block variable inside content -> Option CQuick Check:
Dynamic block content uses each.value [OK]
- Using block_name.value inside dynamic block content instead of each.value
- Trying to use for_each on resource incorrectly
- Forgetting to define for_each on dynamic block
variable "users" {
type = map(object({
policies = list(object({
name = string
policy = string
}))
}))
}Solution
Step 1: Manage multiple users
Use for_each on aws_iam_user resource to create one user per map entry.Step 2: Manage multiple policies per user
Since policies are separate resources (aws_iam_user_policy), use for_each on that resource to create one policy per user-policy pair.Step 3: Why not dynamic blocks here?
Dynamic blocks repeat nested blocks inside a resource, but aws_iam_user_policy is a separate resource, so for_each is appropriate.Final Answer:
Use for_each on aws_iam_user for users, and for_each on aws_iam_user_policy for policies -> Option AQuick Check:
Multiple resources = for_each on both [OK]
- Using dynamic blocks to create multiple resources
- Using count instead of for_each for maps
- Trying to nest policies inside user resource with dynamic blocks
Ready to prove it?
Pass the test and this pattern moves unknown
