Dynamic Blocks is for Complex Nested Configurations

Dynamic blocks account for 15-20% of code organization questions and are particularly confusing when it comes to nesting and scope.

The Problem

# Verbose, repetitive configuration
resource "aws_security_group" "example" {
  name = "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"]
  }
  
  # Many more ingress blocks...
}

The Solution

# Using dynamic blocks
locals {
  ports = [80, 443, 8080, 8443]
}

resource "aws_security_group" "example" {
  name = "example"
  
  dynamic "ingress" {
    for_each = toset(local.ports)
    content {
      from_port   = ingress.value
      to_port     = ingress.value
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  }
}

Dynamic blocks drastically reduce repetition, but can be hard to debug. Tools like Scalr's enhanced plan output help by clearly visualizing the resources that will be generated, making it easier to catch mistakes before they're applied.