100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
HCL

Dynamic Blocks

Learn how to generate repeated nested configuration blocks programmatically inside a resource, avoiding hand-written repetition for variable-length nested settings.

Resource Graph & DependenciesAdvanced8 min readJul 9, 2026
Analogies

Dynamic Blocks

count and for_each let you repeat an entire resource or module, but many resources also contain nested configuration blocks — like ingress rules inside a security group, or tag blocks inside an autoscaling group — whose number varies depending on input rather than being fixed at one. Hand-writing each nested block for every possible case doesn't scale when the number of rules comes from a variable. The dynamic block construct solves this by generating a nested block once for each element of a given collection, directly inside the resource, exactly the way for_each generates whole resources.

🏏

Cricket analogy: count and for_each can field a full XI of identical resources, but a captain still needs to vary the number of slip fielders per over depending on the bowler; a dynamic block lets that inner field-placement block repeat as many times as the situation calls for.

Anatomy of a dynamic block

A dynamic block starts with the keyword dynamic followed by the name of the nested block type you want to repeat, such as dynamic "ingress". Inside it, for_each specifies the collection to iterate, and a nested content block defines the body that gets emitted once per iteration. Within that content block, a special iterator variable — named after the block type by default, or renamed with the iterator argument — exposes .key and .value for the current element, mirroring the each object used in a resource-level for_each.

🏏

Cricket analogy: Writing dynamic "ingress" is like a scorer labeling a wagon-wheel diagram; for_each supplies the list of shots, and the content block, using .value for each shot's angle, draws one wedge per delivery just like the each object drives a resource loop.

hcl
variable "ingress_rules" {
  type = list(object({
    description = string
    port        = number
    cidr_blocks = list(string)
  }))
  default = [
    { description = "HTTPS", port = 443, cidr_blocks = ["0.0.0.0/0"] },
    { description = "SSH from office", port = 22, cidr_blocks = ["203.0.113.0/24"] },
  ]
}

resource "aws_security_group" "app" {
  name   = "app-sg"
  vpc_id = aws_vpc.main.id

  dynamic "ingress" {
    for_each = var.ingress_rules
    content {
      description = ingress.value.description
      from_port   = ingress.value.port
      to_port     = ingress.value.port
      protocol    = "tcp"
      cidr_blocks = ingress.value.cidr_blocks
    }
  }
}

Renaming the iterator

When a dynamic block is nested inside another dynamic block, or when the default iterator name would be confusing, the iterator argument lets you assign a custom name to the loop variable. This is purely cosmetic for readability — it does not change the semantics of the loop — but it becomes essential once you nest dynamic blocks two or three levels deep, where the outer and inner blocks would otherwise both try to use the same default name.

🏏

Cricket analogy: When commentary nests a powerplay analysis inside an over-by-over review, the broadcaster renames the inner loop variable from 'over' to 'ball' so viewers aren't confused about which counter is which, purely for clarity, not for the scoring math.

hcl
dynamic "setting" {
  for_each = var.elasticbeanstalk_settings
  iterator = setting_item
  content {
    namespace = setting_item.value.namespace
    name      = setting_item.value.name
    value     = setting_item.value.value
  }
}

A dynamic block is conceptually a for loop that emits HCL blocks rather than a for expression that emits values — it belongs inside a resource, data source, provider, or provisioner block wherever a repeatable nested block type is normally allowed by that block's schema.

The Terraform documentation itself cautions against overusing dynamic blocks: when a nested block's structure is simple and mostly static, hand-writing it directly is more readable and easier to review than wrapping it in dynamic/for_each machinery. Reach for dynamic blocks when the number or content of nested blocks is genuinely driven by variable input, not as a default style choice.

Dynamic blocks vs top-level for_each

It is easy to confuse dynamic blocks with the resource-level for_each meta-argument, but they solve different problems: resource-level for_each multiplies an entire resource into many state-tracked instances, while a dynamic block multiplies a nested block within a single resource instance and produces no separate state entries of its own — the generated nested blocks are just part of that one resource's configuration and are tracked as attributes of it, not as independently addressable objects.

🏏

Cricket analogy: Selecting a fixed XI as separate contracted players is like resource-level for_each creating independently tracked instances, whereas varying the number of boundary fielders within one player's over is like a dynamic block — no new player is added to the squad.

  • Dynamic blocks generate repeated nested configuration blocks inside a single resource, based on a for_each collection.
  • The content block defines the body to emit for each iteration; the iterator variable (default name equals the block label) exposes .key and .value.
  • The iterator argument renames the loop variable, which is necessary when nesting dynamic blocks.
  • Unlike resource-level for_each, dynamic blocks don't create separate, independently addressable state entries.
  • Overusing dynamic blocks for simple, mostly-static nested blocks hurts readability — use them only when the structure genuinely varies.
  • Dynamic blocks can appear inside resources, data sources, providers, and provisioners wherever repeatable nested blocks are schema-permitted.

Practice what you learned

Was this page helpful?

Topics covered

#HCL#TerraformInfrastructureAsCodeStudyNotes#DevOps#DynamicBlocks#Dynamic#Blocks#Anatomy#Block#StudyNotes#SkillVeris