Terraform Fundamentals · Module 04 of 12

Expressions, collections, count and for_each

Use Terraform expressions and collection types deliberately, then choose stable resource instance keys instead of creating brittle index-based infrastructure.

Learning objectives

By the end of this module, you should be able to:

  • Work with lists, sets, maps, for expressions and conditionals.
  • Choose between count and for_each.
  • Explain why stable keys reduce address churn.

Expressions transform values

Terraform expressions combine literals, references, operators, functions, conditionals and for expressions. Collection transformations are central to reusable infrastructure.

count creates numeric instances

count is concise when instances are truly interchangeable and positional. Removing an item from the middle of a positional list can shift indexes and cause surprising address changes.

for_each uses stable keys

for_each accepts a map or set of strings. Keys become part of resource addresses, making identity explicit and usually safer for named infrastructure.

Worked examples

See the idea in practice.

Stable service instances

variable "services" {
  type = map(number)
  default = {
    api    = 2
    worker = 1
  }
}

resource "terraform_data" "service" {
  for_each = var.services
  input = {
    name     = each.key
    replicas = each.value
  }
}
  • Addresses remain keyed by api and worker rather than numeric positions.
Hands-on lab

Lab — Model stable instances with for_each

Goal: Create keyed instances and derive a map output with a for expression.

Before you start

  • Terraform CLI only.
STEP 1

Write keyed configuration

mkdir -p ~/gnu-terraform-labs/module04 && cd ~/gnu-terraform-labs/module04
cat > main.tf <<'EOF'
variable "services" {
  type = map(number)
  default = {
    api    = 2
    worker = 1
    jobs   = 1
  }
}

resource "terraform_data" "service" {
  for_each = var.services
  input = {
    name     = each.key
    replicas = each.value
  }
}

output "replicas" {
  value = { for k, v in terraform_data.service : k => v.output.replicas }
}
EOF
STEP 2

Apply

terraform init
terraform apply -auto-approve
STEP 3

Inspect addresses

terraform state list
STEP 4

Inspect derived map

terraform output replicas

Verify

  • Three instances exist with string keys.
  • The output maps each service key to its replica value.

Expected outcome

  • You can choose stable keys instead of relying on positional identity.

If it fails

  • for_each keys must be known before apply.
  • Convert a list of unique strings with toset when only membership matters.
Real-world connection

Stable instance identity reduces accidental replacement during list reordering and makes state addresses easier to reason about.

Avoid these traps

Common mistakes

  • Using count for named objects whose identity should survive reordering.
  • Using duplicate values in a set and expecting duplicates to remain.
  • Trying to derive for_each keys from values unknown until apply.
Knowledge check

Can you explain it without looking back?

Open each answer only after you have tried to answer the question yourself.

1When is for_each usually preferable to count?

When instances have meaningful stable keys or names.

2What becomes part of a for_each resource address?

The map or set key.

3Why can count be brittle with reordered lists?

Numeric indexes can shift, changing which address maps to which intended object.

My Learning

Record your progress for this module.

Progress is saved in this browser immediately. When you sign in to My Learning, it can also sync across devices.

Not started

Attempt the core lab and knowledge checks before marking the module complete.