IntermediateLesson 7 of 16

Expressions, Loops & Dependencies

Use Terraform’s expression language to build flexible infrastructure without turning your configuration into unreadable logic soup.

🧒 Simple Explanation (ELI5)

Sometimes you need one subnet. Sometimes you need five. Sometimes one environment needs diagnostics and another does not. Terraform expressions let you calculate values and repeat blocks without copying everything by hand.

🤔 Why Do We Need It?

🔧 Technical Explanation

Terraform supports expressions, built-in functions, conditional logic, and resource repetition through for_each and count. Implicit dependencies are derived from references. Explicit depends_on is reserved for cases where Terraform cannot infer the relationship.

hcl
variable "subnets" {
  type = map(string)
}

resource "azurerm_subnet" "this" {
  for_each             = var.subnets
  name                 = each.key
  resource_group_name  = azurerm_resource_group.platform.name
  virtual_network_name = azurerm_virtual_network.platform.name
  address_prefixes     = [each.value]
}
FeatureUse Carefully For
for_eachNamed repeated infrastructure objects
countSimple numeric repetition or optional resources
Conditional expressionsEnvironment-specific decisions
depends_onOnly when implicit references are not enough
💡
Practical Preference

Prefer for_each over count when resources have stable names or identities. It is usually easier to understand and less fragile during change.

🌍 Real-World Use Case

A shared Azure networking module might accept a map of subnets and generate them dynamically, while an AKS module conditionally enables diagnostics in production only. That keeps the platform flexible without duplicating entire modules.

🛠️ Hands-on

Dynamic Subnet Creation

hcl
variable "subnets" {
  default = {
    app = "10.10.1.0/24"
    db  = "10.10.2.0/24"
    aks = "10.10.3.0/24"
  }
}

Conditional Tags

hcl
locals {
  monitoring_enabled = var.environment == "prod"
}

🐛 Debugging Scenario

Problem: Resources are getting recreated unexpectedly after changing a list or order.

This often happens when count is tied to positional lists. A change in ordering can remap indexes and make Terraform think resources changed identity. Using for_each with stable keys usually avoids that class of issue.

⚠️
Logic Smell

If your Terraform starts to look like a programming contest solution, you probably need a clearer module boundary, not more clever expressions.

📋 Interview Questions

Beginner

What is for_each used for?

It creates multiple instances of a resource or module based on a map or set, usually with stable keys.

When would you use count?

For simple numeric repetition or optional resource creation, though it can be more fragile than for_each for identity.

How does Terraform know one resource depends on another?

Usually through references in expressions. That creates implicit dependencies automatically.

What does depends_on do?

It explicitly declares a dependency when Terraform cannot infer it correctly from expressions alone.

Why are stable keys important?

They help Terraform track resource identity safely across changes.

Intermediate

Why is for_each often safer than count?

Because resource identity is tied to explicit keys rather than numeric indexes that can shift when lists change order.

When should depends_on be avoided?

When a normal reference already expresses the dependency. Overusing depends_on hides the real design and makes plans harder to reason about.

What is a common anti-pattern with expressions?

Building highly complex conditional logic that makes infrastructure behavior difficult to understand and review.

How would you model repeated subnet creation well?

Use a map keyed by subnet name and iterate with for_each so identity remains stable.

What does implicit dependency buy you?

Cleaner configuration and more accurate graph building without unnecessary manual dependency declarations.

Scenario-Based

A subnet got replaced because someone reordered a list. What should change?

I would move from count-based positional indexing to for_each with stable keys so order no longer defines identity.

Why might an AKS resource need explicit depends_on?

Sometimes the underlying dependency is operational rather than directly referenced in an expression, such as role assignments needing to exist before a cluster action completes reliably.

Your Terraform code became hard to review after adding many conditionals. What is the fix?

Simplify the logic, push repeated patterns into modules, and prefer clarity over cleverness.

How do you keep dynamic infrastructure understandable for juniors?

Use descriptive variable names, stable keys, and keep the data structure simple enough that reviewers can mentally expand the result.

What is your rule for adding depends_on?

I add it only when the dependency is real and Terraform cannot infer it naturally from resource references.

🧾 Summary

Terraform expressions and repetition features are powerful, but the real skill is using them without sacrificing readability and safe resource identity.