0
0
Terraformcloud~5 mins

Count vs for_each decision in Terraform - CLI Comparison

Choose your learning style9 modes available
Introduction
When creating multiple similar resources in Terraform, you can use count or for_each to repeat resources. Choosing the right one helps manage resources clearly and avoid errors.
When you want to create a fixed number of identical resources without unique identifiers.
When you need to create resources based on a list of values where order matters.
When you want to create resources with unique keys or names from a map or set.
When you want to update or remove specific resources without affecting others.
When you want to reference each resource individually by a meaningful key.
Config File - main.tf
main.tf
terraform {
  required_version = ">= 1.0"
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "count_example" {
  count = 3
  bucket = "my-bucket-count-${count.index}"
  acl    = "private"
}

resource "aws_s3_bucket" "foreach_example" {
  for_each = {
    bucket1 = "my-bucket-foreach-1"
    bucket2 = "my-bucket-foreach-2"
    bucket3 = "my-bucket-foreach-3"
  }
  bucket = each.value
  acl    = "private"
}

This Terraform file shows two ways to create multiple AWS S3 buckets.

count_example uses count to create 3 buckets named with numbers (0,1,2). This is good for identical resources without unique keys.

foreach_example uses for_each with a map to create buckets with specific names. This lets you manage each bucket by its key (bucket1, bucket2, bucket3).

Commands
Initializes the Terraform working directory and downloads the AWS provider plugin.
Terminal
terraform init
Expected OutputExpected
Initializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/aws... - Installing hashicorp/aws v4.0.0... - Installed hashicorp/aws v4.0.0 (signed by HashiCorp) Terraform has been successfully initialized!
Shows the resources Terraform will create using count and for_each, so you can review before applying.
Terminal
terraform plan
Expected OutputExpected
An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_s3_bucket.count_example[0] will be created + resource "aws_s3_bucket" "count_example" { + acl = "private" + bucket = "my-bucket-count-0" + id = (known after apply) } # aws_s3_bucket.count_example[1] will be created + resource "aws_s3_bucket" "count_example" { + acl = "private" + bucket = "my-bucket-count-1" + id = (known after apply) } # aws_s3_bucket.count_example[2] will be created + resource "aws_s3_bucket" "count_example" { + acl = "private" + bucket = "my-bucket-count-2" + id = (known after apply) } # aws_s3_bucket.foreach_example["bucket1"] will be created + resource "aws_s3_bucket" "foreach_example" { + acl = "private" + bucket = "my-bucket-foreach-1" + id = (known after apply) } # aws_s3_bucket.foreach_example["bucket2"] will be created + resource "aws_s3_bucket" "foreach_example" { + acl = "private" + bucket = "my-bucket-foreach-2" + id = (known after apply) } # aws_s3_bucket.foreach_example["bucket3"] will be created + resource "aws_s3_bucket" "foreach_example" { + acl = "private" + bucket = "my-bucket-foreach-3" + id = (known after apply) } Plan: 6 to add, 0 to change, 0 to destroy.
Creates the S3 buckets as planned without asking for confirmation.
Terminal
terraform apply -auto-approve
Expected OutputExpected
aws_s3_bucket.count_example[0]: Creating... aws_s3_bucket.count_example[1]: Creating... aws_s3_bucket.count_example[2]: Creating... aws_s3_bucket.foreach_example["bucket1"]: Creating... aws_s3_bucket.foreach_example["bucket2"]: Creating... aws_s3_bucket.foreach_example["bucket3"]: Creating... aws_s3_bucket.count_example[0]: Creation complete after 2s [id=my-bucket-count-0] aws_s3_bucket.count_example[1]: Creation complete after 2s [id=my-bucket-count-1] aws_s3_bucket.count_example[2]: Creation complete after 2s [id=my-bucket-count-2] aws_s3_bucket.foreach_example["bucket1"]: Creation complete after 2s [id=my-bucket-foreach-1] aws_s3_bucket.foreach_example["bucket2"]: Creation complete after 2s [id=my-bucket-foreach-2] aws_s3_bucket.foreach_example["bucket3"]: Creation complete after 2s [id=my-bucket-foreach-3] Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
-auto-approve - Skip manual approval to apply changes immediately
Lists all resources Terraform manages, showing how count and for_each resources are named differently.
Terminal
terraform state list
Expected OutputExpected
aws_s3_bucket.count_example[0] aws_s3_bucket.count_example[1] aws_s3_bucket.count_example[2] aws_s3_bucket.foreach_example["bucket1"] aws_s3_bucket.foreach_example["bucket2"] aws_s3_bucket.foreach_example["bucket3"]
Key Concept

If you remember nothing else from this pattern, remember: use count for simple repeated identical resources and for_each when you need to manage resources by unique keys or names.

Common Mistakes
Using count with a map or set of strings instead of a list.
Count only works with numbers and lists indexed by numbers, so it cannot handle unique keys or unordered sets.
Use for_each with maps or sets to create resources with unique keys.
Changing the order of a list used with count to identify resources.
Terraform tracks resources by index with count, so changing order can cause resource replacement or errors.
Use for_each with keys to avoid order dependency.
Trying to access resource attributes using keys when count is used.
Resources with count are indexed by numbers, not keys, so key-based access fails.
Use count.index for numeric access or switch to for_each for key-based access.
Summary
Use count to create multiple identical resources indexed by numbers.
Use for_each to create resources with unique keys from maps or sets.
Run terraform init, plan, apply, and state list to manage and verify resources.