Bird
Raised Fist0
Terraformcloud~5 mins

Count vs for_each decision in Terraform - CLI Comparison

Choose your learning style10 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.

Practice

(1/5)
1. Which Terraform argument should you use when you want to create 3 identical resources without unique identifiers?
easy
A. count = 3
B. for_each = {}
C. for_each = toset(["a", "b", "c"])
D. count = 0

Solution

  1. Step 1: Understand the purpose of count

    count creates multiple copies of a resource by number, perfect for identical resources.
  2. Step 2: Compare with for_each

    for_each is used when you want unique keys or values to identify each resource, not just copies.
  3. Final Answer:

    count = 3 -> Option A
  4. Quick Check:

    Simple copies = count [OK]
Hint: Use count for number copies, for_each for unique keys [OK]
Common Mistakes:
  • Using for_each when only number copies are needed
  • Setting count to zero expecting resources
  • Confusing sets with counts
2. Which of the following is the correct syntax to create resources using for_each with a map in Terraform?
easy
A. resource "aws_instance" "example" { for_each = ["a", "b"] }
B. resource "aws_instance" "example" { for_each = "string" }
C. resource "aws_instance" "example" { count = 2 }
D. resource "aws_instance" "example" { for_each = { key1 = "val1", key2 = "val2" } }

Solution

  1. Step 1: Identify valid for_each types

    for_each accepts maps or sets, not lists or strings directly.
  2. Step 2: Check each option

    resource "aws_instance" "example" { for_each = { key1 = "val1", key2 = "val2" } } uses a map with keys and values, which is valid syntax for for_each.
  3. Final Answer:

    resource with for_each map -> Option D
  4. Quick Check:

    for_each needs map or set [OK]
Hint: for_each needs map or set, not list or string [OK]
Common Mistakes:
  • Using list instead of map/set for for_each
  • Confusing count with for_each syntax
  • Passing string directly to for_each
3. Given this Terraform snippet:
resource "aws_s3_bucket" "buckets" {
  for_each = { bucket1 = "private", bucket2 = "public-read" }
  bucket = each.key
  acl = each.value
}

What will be the names of the created buckets?
medium
A. ["each.key", "each.value"]
B. ["private", "public-read"]
C. ["bucket1", "bucket2"]
D. No buckets created due to syntax error

Solution

  1. Step 1: Understand for_each map keys and values

    The keys are bucket1 and bucket2, values are ACL values.
  2. Step 2: Check bucket assignment

    The bucket name is set to each.key, so buckets named "bucket1" and "bucket2" are created.
  3. Final Answer:

    ["bucket1", "bucket2"] -> Option C
  4. Quick Check:

    Bucket names = map keys [OK]
Hint: for_each keys become resource identifiers [OK]
Common Mistakes:
  • Using values as bucket names instead of keys
  • Assuming syntax error without checking
  • Confusing each.key with each.value
4. You wrote this Terraform resource:
resource "aws_instance" "example" {
  count = length(var.instances)
  name  = var.instances[count.index]
}

But Terraform throws an error about count.index. What is the likely cause?
medium
A. count is used but for_each should be used for maps
B. var.instances is a map, but count expects a list
C. You cannot use count.index inside resource blocks
D. count must be a fixed number, not a variable

Solution

  1. Step 1: Identify variable type mismatch

    var.instances is likely a map, but count works with numbers and lists indexed by numbers.
  2. Step 2: Choose correct iterator

    For maps, for_each is the correct choice to iterate over keys and values.
  3. Final Answer:

    Use for_each for maps, not count -> Option A
  4. Quick Check:

    Maps need for_each, not count [OK]
Hint: Use for_each for maps, count for lists [OK]
Common Mistakes:
  • Using count.index with maps
  • Assuming count must be fixed number
  • Ignoring variable data type
5. You want to create multiple AWS IAM users with unique usernames and policies from this map:
users = {
  alice = "admin",
  bob = "read-only",
  carol = "power-user"
}

Which Terraform resource block correctly uses count or for_each to create these users with unique names?
hard
A.
resource "aws_iam_user" "user" {
  count = length(keys(var.users))
  name  = keys(var.users)[count.index]
  policy = var.users[name]
}
B.
resource "aws_iam_user" "user" {
  for_each = var.users
  name     = each.key
  policy   = each.value
}
C.
resource "aws_iam_user" "user" {
  count = 3
  name  = var.users[count.index]
  policy = var.users[count.index]
}
D.
resource "aws_iam_user" "user" {
  for_each = toset(var.users)
  name     = each.value
  policy   = each.key
}

Solution

  1. Step 1: Analyze data structure

    The users variable is a map with usernames as keys and policies as values.
  2. Step 2: Match iteration method

    for_each works well with maps to create uniquely identified resources using keys and values.
  3. Step 3: Check each option

    resource "aws_iam_user" "user" {
      for_each = var.users
      name     = each.key
      policy   = each.value
    }
    correctly uses for_each = var.users and assigns name = each.key and policy = each.value.
  4. Final Answer:

    Use for_each with map for unique users -> Option B
  5. Quick Check:

    Unique keys need for_each [OK]
Hint: Use for_each with maps for unique resource keys [OK]
Common Mistakes:
  • Using count with maps incorrectly
  • Mixing keys and values in wrong order
  • Using toset on maps causing errors
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard