/compare/terraform/count-vs-for-each
Terraform count vs for_each: which one to use
verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · Terraform v1.16.6updated 2026-10-20
- tool
- Terraform
- compares
- count vs for_each
count = N creates N instances addressed by position: res[0], res[1]. for_each takes a map or a set of strings and addresses instances by key: res["web"]. Use for_each whenever the instances have their own identity, and keep count for identical copies or for an on/off switch (count = var.enabled ? 1 : 0).
Same list, two addresses
cat > main.tf <<'EOF'
variable "names" {
type = list(string)
default = ["web", "api", "worker"]
}
resource "terraform_data" "by_count" {
count = length(var.names)
input = var.names[count.index]
}
resource "terraform_data" "by_each" {
for_each = toset(var.names)
input = each.key
}
EOF
terraform init -input=false -no-color >/dev/null
terraform plan -no-color -input=false | grep 'will be created'Output
# terraform_data.by_count[0] will be created # terraform_data.by_count[1] will be created # terraform_data.by_count[2] will be created # terraform_data.by_each["api"] will be created # terraform_data.by_each["web"] will be created # terraform_data.by_each["worker"] will be created
Criterion by criterion
| Criterion | count | for_each |
|---|---|---|
| Address | res[0], res[1], … | res["web"], res["api"], … |
| Remove the first item of the list | every later instance shifts index: Terraform updates or replaces them | only res["web"] is destroyed |
| Input | a whole number | a map, or a set of strings (toset(list)) |
| Inside the block | count.index | each.key, each.value |
| Values known at plan time | the number must be known | the keys must be known |
| Good for | N identical copies, or 0/1 conditional resources | named things: buckets, users, subnets |
Switching from count to for_each
Changing the meta-argument changes every address, so without help Terraform would destroy and recreate everything. Add moved blocks to keep the existing objects:
moved {
from = terraform_data.by_count[0]
to = terraform_data.by_each["web"]
}Sources
Related pages
cheat sheets · terraformTerraform cheat sheet: init, plan, apply, state and workspacesTerraform cheat sheet: init and upgrade, fmt and validate, plan and apply, outputs, state list, mv and rm, import, workspaces, and common language syntax.glossary · terraformWhat is Terraform state?Terraform state is the JSON record that maps each resource address in your code to the real object it manages and its last known attributes: terraform.tfstate.config · terraformTerraform variable precedence: tfvars, auto.tfvars, -var and TF_VAR_Terraform reads variables from TF_VAR_ environment variables, terraform.tfvars, *.auto.tfvars, then -var-file and -var. Later sources win, shown with plans.