Thuta Learning
AdvancedDevOpsintermediate

Loops & Conditionals (count, for_each, dynamic)

Relax. We'll talk through this in plain words — no textbook voice.

What you'll walk away with

  • Understand Loops & Conditionals (count, for_each, dynamic) without any of the intimidation
  • Get hands-on running terraform commands and HCL code yourself
  • Apply this concept in a real project right away

Let's think about it this way for a second

Instead of manually copy-pasting five resource blocks for five servers, adding `count = 5` inside a resource block makes Terraform create it five times over — you can use `count.index` (0,1,2,3,4) in the resource name/tag. `for_each` is for looping over a list/map — it's better than `count` when you want to track items by a 'meaningful key' (like a server name) instead of an index number (0,1,2): if you delete one item from a list, `count` shifts every index and can recreate every resource, while `for_each` leaves the rest of the items untouched. A dynamic block, meanwhile, is for generating nested blocks (like multiple `ingress` rules in a security group) with a loop.

Let's connect this to a real scenario

Writing `for_each = toset(["web", "api", "worker"])` creates three servers (named web, api, worker) — you can reference `each.key`/`each.value` inside the resource. If you delete 'api' from the server list, `for_each` destroys only 'api' and leaves 'web'/'worker' completely untouched — with `count`, the index shift could recreate every server.

Let's look at it together

hcl
# count: index-based
resource "aws_instance" "worker" {
  count         = 3
  ami           = "ami-0abcdef1234567890"
  instance_type = "t3.micro"
  tags = {
    Name = "worker-${count.index}"
  }
}

# for_each: key-based (safer when removing items)
resource "aws_instance" "app" {
  for_each      = toset(["web", "api", "worker"])
  ami           = "ami-0abcdef1234567890"
  instance_type = "t3.micro"
  tags = {
    Name = each.value
  }
}
You should see
$ terraform apply
aws_instance.app["api"]: Creating...
aws_instance.app["web"]: Creating...
aws_instance.app["worker"]: Creating...

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

5-minute try-it

Use `for_each` to create three `local_file` resources at once (with different filenames) — delete one item from the list, re-run `apply`, and confirm the remaining files are untouched.

A quick word of caution

You can't use `count` and `for_each` together on the same resource — you have to pick one or the other for each resource type.

Easy traps

  • Using `count` in production without realizing that deleting an item from the middle of a list shifts every resource's index and can trigger a recreate
  • Passing a list directly to `for_each` without wrapping it in `toset()` — `for_each` only accepts a set or map, so a list needs to be converted with toset()

Now try it yourself

Use `for_each` to create three `local_file` resources at once (with different filenames) — delete one item from the list, re-run `apply`, and confirm the remaining files are untouched.

You'll know it worked when: $ terraform apply aws_instance.app["api"]: Creating... aws_instance.app["web"]: Creating... aws_instance.app["worker"]: Creating... Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Loops & Conditionals (count, for_each, dynamic) | Thuta Learning