Terraform Tutorial · Terraform Language · Lesson 13 of 25
Terraform count and for_each
Create several copies of a resource with count or for_each, and learn why for_each is usually the safer choice.
count
count creates N copies, numbered from 0, addressed as aws_instance.web[0], [1], …
resource "aws_instance" "web" {
count = 3
ami = var.ami
instance_type = "t3.micro"
tags = { Name = "web-${count.index}" }
}
count = var.enabled ? 1 : 0 is the classic way to create a resource conditionally.
for_each
for_each creates one copy per map key or set element, addressed by key: aws_s3_bucket.this["logs"].
terraform {
required_providers {
local = { source = "hashicorp/local", version = "~> 2.5" }
}
}
resource "local_file" "env" {
for_each = {
dev = "debug=true"
prod = "debug=false"
}
filename = "${path.module}/${each.key}.env"
content = each.value
}
Output
Terraform will perform the following actions:
# local_file.env["dev"] will be created
+ resource "local_file" "env" {
+ content = "debug=true"
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./dev.env"
+ id = (known after apply)
}
# local_file.env["prod"] will be created
+ resource "local_file" "env" {
+ content = "debug=false"
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./prod.env"
+ id = (known after apply)
}
Plan: 2 to add, 0 to change, 0 to destroy.Run this on your computer — see “Get Started” for setup.
Why for_each is usually better
With count, copies are identified by position. Remove the first item of a list and every later item
shifts, so Terraform destroys and re-creates them. With for_each, copies are identified by key, so removing
one item affects only that item.
locals {
names = ["alpha", "beta", "gamma"]
}
output "count_style_addresses" {
value = [for i, n in local.names : "server[${i}] = ${n}"]
}
output "for_each_style_addresses" {
value = [for n in local.names : "server[\"${n}\"]"]
}
Output
count_style_addresses = [ "server[0] = alpha", "server[1] = beta", "server[2] = gamma", ] for_each_style_addresses = [ "server[\"alpha\"]", "server[\"beta\"]", "server[\"gamma\"]", ]
Run this on your computer — see “Get Started” for setup.
Test yourself
You remove the first of three servers created with count. What happens to the other two?
NothingThey are replaced, because their indexes shiftThey are importedTerraform refuses to plan
Show answer
Answer: They are replaced, because their indexes shift