Table of Contents

count vs for_each: Which Should You Use?

Both count and for_each create multiple instances of a resource, but they behave differently and have different use cases.

Quick Answer

Featurecountfor_each
Index typeNumeric (0, 1, 2…)String key
ReorderingCauses recreationSafe
Conditionalcount = var.enabled ? 1 : 0N/A
Best forSimple on/off, identical copiesDistinct items with unique keys

Use count When

Creating identical copies or toggling resources on/off:

resource "aws_instance" "web" {
  count         = var.instance_count
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  tags = {
    Name = "web-${count.index}"
  }
}

Conditionally creating a resource:

resource "aws_cloudwatch_metric_alarm" "high_cpu" {
  count = var.enable_monitoring ? 1 : 0
  # ... alarm configuration
}

Use for_each When

Creating resources from a map or set with meaningful keys:

resource "aws_iam_user" "team" {
  for_each = toset(["alice", "bob", "charlie"])
  name     = each.value
}

Resources identified by name rather than index:

variable "buckets" {
  default = {
    logs    = { acl = "log-delivery-write" }
    assets  = { acl = "private" }
    backups = { acl = "private" }
  }
}

resource "aws_s3_bucket" "this" {
  for_each = var.buckets
  bucket   = "${var.project}-${each.key}"
}

Why for_each Is Usually Better

With count, removing an item from the middle of a list causes all subsequent resources to be recreated:

# count = ["a", "b", "c"] → remove "b" → "c" shifts to index 1 → RECREATED

With for_each, each resource is keyed by name, so removing one doesn’t affect others.

Common Pitfall

for_each keys must be known at plan time. This fails:

# ERROR: for_each depends on resource that hasn't been created yet
resource "aws_subnet" "this" {
  for_each = toset(aws_availability_zones.available.names)  # Unknown at plan!
}

Fix: Use a data source or variable instead.

Learn More