Skip to main content
RunBook Academy

← All labs in Terraform

Lab · intermediate · ~20 min

Lab: count vs for_each for Resource Instances

C · Simulation

Objectives

  • Demonstrate the lab scenario
  • Verify the expected outcome

Prerequisites

Objective

By the end of this lab, you will have:

  • Created a configuration with multiple instances using count.
  • Created a configuration with multiple instances using for_each.
  • Verified that count is identity-fragile.
  • Verified that for_each is identity-stable.

Requirements

  • A Linux or macOS workstation with shell access.
  • The Terraform CLI 1.9.x or later installed.

Scenario

You have a configuration that needs to create multiple files. You are choosing between count and for_each. The choice has implications for refactoring and state stability.

Tasks

Task 1: Create the working directory

mkdir -p ~/rb-count-vs-foreach
cd ~/rb-count-vs-foreach
mkdir -p count foreach
cd ~/rb-count-vs-foreach

Task 2: Create the count configuration

Create count/main.tf:

terraform {
  required_version = ">= 1.9.0"
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.5"
    }
  }
}

resource "local_file" "readme" {
  count = 3

  filename = "${path.module}/count-${count.index}.txt"
  content  = "File from count, index ${count.index}\n"
}

Task 3: Apply the count configuration

cd count
terraform init
terraform apply

Verify:

ls count-*.txt
cat count-0.txt

Task 4: Modify the count

Change the count from 3 to 2:

resource "local_file" "readme" {
  count = 2
  ...
}

Apply:

terraform apply

Verify:

ls count-*.txt

The count-2.txt file is destroyed. The remaining files are count-0.txt and count-1.txt.

This is the count antipattern: changing the count can destroy real-world resources.

Task 5: Create the for_each configuration

Create foreach/main.tf:

terraform {
  required_version = ">= 1.9.0"
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.5"
    }
  }
}

resource "local_file" "readme" {
  for_each = toset(["a", "b", "c"])

  filename = "${path.module}/foreach-${each.key}.txt"
  content  = "File from for_each, key ${each.key}\n"
}

Task 6: Apply the for_each configuration

cd ../foreach
terraform init
terraform apply

Verify:

ls foreach-*.txt
cat foreach-a.txt

Task 7: Modify the for_each

Remove the key “b” from the set:

resource "local_file" "readme" {
  for_each = toset(["a", "c"])
  ...
}

Apply:

terraform apply

Verify:

ls foreach-*.txt

The foreach-b.txt file is destroyed. The foreach-a.txt and foreach-c.txt files are unchanged.

This is the for_each advantage: changing the keys only affects the changed keys.

Task 8: Add a new key

Add the key “d” to the set:

resource "local_file" "readme" {
  for_each = toset(["a", "c", "d"])
  ...
}

Apply:

terraform apply

Verify:

ls foreach-*.txt

The foreach-d.txt file is created.

Validation

The lab is successful if:

  • The count configuration created 3 files and then destroyed 1.
  • The for_each configuration created 3 files, destroyed 1, and created 1.

Expected Outcome

After the count experiment:

count-0.txt
count-1.txt

After the for_each experiment:

foreach-a.txt
foreach-c.txt
foreach-d.txt

Cleanup

cd ~/rb-count-vs-foreach
rm -rf count foreach

What You Learned

You learned the count vs for_each trade-off:

  • count is identity-fragile. Changing the count can destroy real-world resources.
  • for_each is identity-stable. Changing the keys only affects the changed keys.
  • For stateful resources, use for_each with a stable semantic key.
  • For ephemeral resources, count is fine.

Deliverables

  • · Two configurations with the same resource count
  • · A demonstration that count is identity-fragile
  • · A demonstration that for_each is identity-stable

Verification status

Last reviewed
2026-08-12
Executed end to end
not yet run on hardware

The commands and configuration here have been reviewed against the verified software versions, but nobody has run this lab start to finish on a system meeting its prerequisites. Treat the Expected Outcome as the intended result rather than an observed one, and keep the Cleanup section to hand.