Choosing between for_each or count in Terraform

Choosing the Right Tool for Iterator between

for_each and count in Terraform:

Terraform's for_each and count meta-arguments are indispensable for creating multiple instances of resources or modules without redundant code. Both enable dynamic infrastructure, but understanding their distinct behaviors is crucial for effective and maintainable configurations.

What are count and for_each?

for_each: This meta-argument iterates over a map or a set of strings. For each item in the collection, Terraform creates a distinct instance of the resource or module, using the map key or set string as a unique identifier.

locals {
  subnets = {
    "subnet_a" = "10.0.1.0/24",
    "subnet_b" = "10.0.2.0/24",
  }
}

resource "aws_subnet" "main" {
  for_each          = local.subnets
  vpc_id            = aws_vpc.main.id
  cidr_block        = each.value # each.key is "subnet_a", "subnet_b"
  # Example for AZ distribution, ensure data source is defined
  # availability_zone = data.aws_availability_zones.available.names[index(keys(local.subnets), each.key)] 

  tags = {
    Name = each.key
  }
}

(Note: For the aws_subnet example, ensure aws_vpc.main and data.aws_availability_zones.available are properly defined in your configuration.)

count: This meta-argument takes a whole number and creates that many instances of a resource or module. Terraform tracks these instances using a numeric index (e.g., aws_instance.example[0], aws_instance.example[1]).

resource "aws_instance" "server_count" {
  count         = 3 # Creates 3 identical instances
  ami           = "ami-0c55b31ad20f0c502"
  instance_type = "t2.micro"
  tags = {
    Name = "Server-${count.index + 1}"
  }
}

Common Sticking Points

The primary confusion arises when deciding between them and understanding the implications:

  • Refactoring and Instance Identity: If you use count and remove an item from the middle of the list that generates the count, Terraform sees it as changing all subsequent resources. This can lead to unintended destruction and recreation. for_each avoids this by using persistent string keys, making it more robust when managing collections where items might be added or removed.
  • Data Structures: count is simpler for basic numerical repetition. for_each requires a map or a set of strings, sometimes necessitating data transformations with functions like toset() or for expressions to prepare the data.
  • Referencing Instances: Accessing specific instances differs: resource_type.name[index] for count vs. resource_type.name["key"] for for_each.

The Scalr Perspective

While Terraform provides the mechanics, managing numerous dynamically created resources across different environments can become complex. A platform like Scalr aids by providing a structured environment where configurations, including those using for_each or count, are executed. Scalr's environment management can ensure that the inputs driving your iterations are consistent and auditable per environment. Furthermore, by using Scalr's policy enforcement (e.g., via OPA), you can set guidelines on how these iterators are used, perhaps flagging potentially risky count scenarios in critical environments, nudging teams towards the more stable for_each where appropriate. Visibility within the Scalr UI into all resources, regardless of how they were created, simplifies tracking.

Summary Table

Feature

count

for_each

Input Type

Number

Map or Set of Strings

Instance ID

Numeric Index (e.g., [0], [1])

String Key (e.g., ["key_a"], ["key_b"])

Stability

Sensitive to order changes in lists

Robust to additions/removals if keys are stable

Use Case

Identical resources, simple repetition

Unique resources from a collection, stable IDs

Common Challenge

Unintended changes when list items shift

Data structure preparation, complex key management

Conclusion

Both for_each and count are powerful. for_each is generally preferred for its stability when managing collections of unique resources. Understanding their differences is key to leveraging Terraform effectively. Platforms like Scalr can then provide the overarching structure and governance to manage these dynamic configurations safely at scale.