Terraform Security:

Last Updated on August 11, 2025 by Arnav Sharma

In Terraform, both `count` and `for_each` are meta-arguments used to create multiple instances of a given resource or module. They enable the `create multiple` infrastructure objects without manually duplicating `terraform code`. They serve different use cases and have distinct behaviors. Here’s a breakdown to help you choose between them.

terraform count

Use case

When you `need to create` a fixed `number of resources` or when you want to create resources based on a `conditional` logic.

Syntax

resource "type" "name" {
  count = 3
  ...
}

Key characteristics

  • It takes a numeric `count value` which is an `integer`.
  • Resources are indexed by a zero-based `index`. E.g., `type.name[0]`, `type.name[1]`, etc.
  • Changing the order or removing elements can cause resources to be destroyed and recreated, as the indices will change.

Pros

  • Simple to use for creating a fixed number of resources.
  • Can be combined with `conditional` logic using Terraform’s dynamic block to decide whether to create a resource.

Cons

  • Not suitable for `dynamic` sets where the order or the number of elements can change frequently.
  • Resource indices might shift if elements are added or removed, leading to potential unintended resource replacements.

for_each in Terraform

Use case

When you want to create resources based on a `set of strings` or a `map or set` of values.

Syntax

resource "type" "name" {
  for_each = toset(["value1", "value2"])
  ...
}

Key characteristics

  • It takes a `data structure` like set or map of values.
  • Resources are indexed by the values in the set/map, not by a numeric index. The `key and value` pair is important.
  • Adding, removing, or reordering elements in the set/map does not cause a shift in resource identities.

Pros

  • Suitable for `dynamic` sets or maps.
  • Order-independent, meaning resources won’t be unintentionally recreated if the order of elements changes.
  • Can use complex data structures (like maps) to create resources with more granularity.

Cons

  • Slightly more complex `basic syntax`, especially when working with maps.
  • Requires a unique `set of strings`. Duplicates will cause errors.

When to use which?

Use `count` when:

  • You want a simple way to `deploy multiple` resources in AWS or Kubernetes.
  • Your `terraform configuration` involves `conditional` creation of resources.  

Use `for_each` when:

  • You’re working with a `dynamic` set or map of values, maybe from a GitHub repo or AWS API.
  •  You want to avoid potential resource replacements due to order changes.
  •  You require more granularity and control over resource creation based on complex data structures.

Comparison Table:

Feature/Characteristic count for_each
Use case Fixed number of resources or conditional creation Based on a set or map of values
Syntax example count = 3 for_each = toset(["value1", "value2"])
Input type Numeric value Set or map of values
Indexing Zero-based integer (e.g., type.name[0]) Values in the set/map (e.g., type.name["value1"])
Order sensitivity Order-sensitive (index might shift) Order-independent
Pros – Simple for fixed number
– Conditional logic support
– Suitable for dynamic sets/maps
– Avoids unintentional resource recreation
Cons – Not suitable for dynamic sets
– Potential resource replacements
– More complex syntax
– Requires unique values

Let’s look at some examples of count and for_each using Azure resources in Terraform.

Using count:

Example 1: Create multiple Azure virtual machines:

resource "azurerm_virtual_machine" "example" {
  count                = 3
  name                 = "vm-${count.index}"
  location             = "East US"
  resource_group_name  = "example-resources"
  vm_size              = "Standard_F2"

  # ... other configurations ...

  tags = {
    environment = "test"
  }
}

In this example, three virtual machines named vm-0, vm-1, and vm-2 will be created.

Example 2: Conditionally create an Azure storage account:

resource "azurerm_storage_account" "example" {
count = var.create_storage ? 1 : 0
name = "storageaccount"
location = "East US"
resource_group_name = "example-resources"
account_tier = "Standard"
account_replication_type = "LRS"

# โ€ฆ other configurations โ€ฆ

}

Here, the storage account will be created only if var.create_storage is set to true.

Using for_each:

Example 1: Create Azure virtual networks based on a map:

variable "vnet_configs" {
  description = "Map of vnet configurations"
  default = {
    vnet1 = "10.0.1.0/24"
    vnet2 = "10.0.2.0/24"
  }
}

resource "azurerm_virtual_network" "example" {
  for_each            = var.vnet_configs
  name                = each.key
  address_space       = [each.value]
  location            = "East US"
  resource_group_name = "example-resources"

  # ... other configurations ...

}

This will create two virtual networks named vnet1 and vnet2 with the respective address spaces.

Example 2: Create Azure resource groups based on a set:

variable "resource_group_names" {
  description = "Set of resource group names"
  default     = ["rg1", "rg2", "rg3"]
}

resource "azurerm_resource_group" "example" {
  for_each = toset(var.resource_group_names)
  name     = each.key
  location = "East US"
}

This will create three resource groups named rg1, rg2, and rg3.

These examples demonstrate how you can utilize count and for_each with Azure resources in Terraform to simplify and streamline infrastructure code.

While both `count` and `for_each` can be used to create multiple instances of resources in Terraform, the choice between them depends on the specific use case and desired behavior. Understanding their characteristics and differences will help in making an informed decision. 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.