Many Copies with count and for_each
Crumb now wants separate buckets for images, menus and logs. Writing three almost identical blocks works, but it is repetitive and easy to get out of step. Terraform's meta-arguments — arguments every resource accepts, whatever its provider — include two for making many objects from one block.
The rule
count for identical copies by number; for_each for named items by key.
count takes a whole number and makes that many objects. Inside the block, count.index is the position, starting at 0.
resource "aws_instance" "web" {
count = 2
ami = "ami-0123456789abcdef0"
instance_type = "t3.micro"
tags = {
Name = "crumb-web-${count.index}"
}
}Addresses: aws_instance.web[0], aws_instance.web[1]. All IDs at once: aws_instance.web[*].id. A common trick is count = var.enable_web ? 1 : 0 to switch a resource on or off.
for_each takes a map, or a set of strings, and makes one object per key. Inside the block, each.key and each.value describe the current item.
resource "aws_s3_bucket" "b" {
for_each = toset(["images", "menus", "logs"])
bucket = "crumb-prod-${each.key}"
}Addresses: aws_s3_bucket.b["images"], aws_s3_bucket.b["menus"], aws_s3_bucket.b["logs"]. For a set, each.value equals each.key; for a map, each.value is the map's value.
The objects are still separate in state. Elsewhere you can refer to one of them, such as aws_s3_bucket.b["logs"].arn, and a plan lists each on its own line, so you always see exactly which copy is changing.
A block may use count or for_each, never both. And the number or keys must be known when planning, not something only created during apply.
The shortcut
Ask "If I remove one from the middle, should the others notice?" They never should, which is why items with names belong in for_each. With count, positions shift.
With count over a list
Buckets are
[0]images,[1]menus,[2]logs.
Use count when the copies are truly interchangeable, or for the on/off switch.
Drills
Answer fast — trust the rule.
With count = 3, what is count.index for the last object?
What is the address of the logs bucket in the for_each example?
Which value can for_each accept directly?
Which line creates a resource only when var.enable_web is true?
Remember
count: copies by number,count.indexfrom 0;for_each: items by key,each.keyandeach.value.- Shortcut: if removing one should not disturb the others, use
for_each. - Trap: never both on one block, and
countindexes shift when a middle item goes.
