Day 10 of my Terraform journey was all about writing less repetitive infrastructure code.
Up to this point, most resources had been declared one by one. That works for small labs, but it becomes painful fast when you need multiple IAM users, repeated rules, or environment-specific behavior.
Today I learned the four Terraform tools that make configurations dynamic:
countfor_each-
forexpressions - ternary conditionals
This was one of the most practical Terraform topics so far.
Why This Matters
Terraform is declarative, but these features make it feel much closer to a programming language.
They help you:
- reduce repetition
- create multiple resources safely
- transform data cleanly
- make infrastructure behavior change by environment
They are also heavily tested in the Terraform Associate exam.
1. Loops with count
count is the simplest loop in Terraform.
Use it when you want Terraform to create a fixed number of similar resources.
resource "aws_iam_user" "example" {
count = 3
name = "user-${count.index}"
}
This creates:
user-0user-1user-2
The important part is count.index, which gives each resource its position.
The count Index Problem
count becomes risky when it is tied to a list that can change.
variable "user_names" {
type = list(string)
default = ["alice", "bob", "charlie"]
}
resource "aws_iam_user" "example" {
count = length(var.user_names)
name = var.user_names[count.index]
}
At first, Terraform maps the list like this:
- index
0→alice - index
1→bob - index
2→charlie
Now imagine I remove alice from the list:
default = ["bob", "charlie"]
Terraform now sees:
- index
0→bob - index
1→charlie
The configuration still runs, but the identities shift. Terraform tracks these resources by position, so when the list changes, later resources can be updated or recreated unexpectedly.
That is why count can be destructive when list order changes.
2. Loops with for_each
for_each solves that problem by using keys or values as identity instead of numeric positions.
variable "user_names" {
type = set(string)
default = ["alice", "bob", "charlie"]
}
resource "aws_iam_user" "example" {
for_each = var.user_names
name = each.value
}
Now Terraform tracks users by value, not by index.
If I remove alice, only alice is affected.
bob and charlie keep their identities.
That makes for_each much safer for collections that may change over time.
for_each with a Map
for_each becomes even more useful when paired with a map.
variable "users" {
type = map(object({
department = string
admin = bool
}))
default = {
alice = { department = "engineering", admin = true }
bob = { department = "marketing", admin = false }
}
}
resource "aws_iam_user" "example" {
for_each = var.users
name = each.key
tags = {
Department = each.value.department
}
}
This lets each item carry extra configuration.
3. for Expressions
for expressions do not create resources. They transform data.
For example, this outputs uppercase names:
output "upper_names" {
value = [for name in var.user_names : upper(name)]
}
And this creates a map of usernames to ARNs:
output "user_arns" {
value = { for name, user in aws_iam_user.example : name => user.arn }
}
A good way to think about it is:
-
countandfor_eachcreate resources -
forexpressions reshape data
4. Ternary Conditionals
Terraform conditionals use this form:
condition ? true_value : false_value
They are useful when you want infrastructure behavior to change based on input.
Example:
variable "environment" {
type = string
default = "dev"
}
locals {
instance_type = var.environment == "production" ? "t2.medium" : "t2.micro"
}
This means:
- if environment is
production, uset2.medium - otherwise use
t2.micro
Then you can use it like this:
resource "aws_instance" "web" {
instance_type = local.instance_type
}
Conditionals with count
Conditionals also work well with count when you want a resource to be optional.
variable "enable_autoscaling" {
description = "Enable autoscaling for the cluster"
type = bool
default = true
}
resource "aws_autoscaling_policy" "scale_out" {
count = var.enable_autoscaling ? 1 : 0
}
This means:
- if
enable_autoscaling = true, create the policy - if
enable_autoscaling = false, skip it
When to Use count vs for_each
This was the biggest lesson of the day.
Use count when:
- you need a fixed number of nearly identical resources
- order does not matter
- the collection is unlikely to change
Use for_each when:
- items have stable names or keys
- the collection may change over time
- each item may have different configuration
In practice, for_each is often safer.
My Main Takeaway
Day 10 made Terraform feel much more dynamic.
The most important lesson for me was this:
-
countis simple -
for_eachis safer -
forexpressions clean up data - conditionals make infrastructure flexible
Together, these four tools make Terraform much more powerful.
Full Code
Follow My Journey
This is Day 10 of my 30-Day Terraform Challenge.
See you on Day 11 🚀
Top comments (0)