Skip to main content
For expressions in Terraform are a data-transformation feature, distinct from count and for_each. While count and for_each control how many resources Terraform creates, for expressions are used to reshape or derive new data structures (lists, sets, maps, strings) from existing inputs. Think of them as a preprocessing step: transform the input data with a for expression, then feed the result into for_each, module inputs, or other resource arguments. Below is a compact example followed by a step‑by‑step explanation.
For expressions only produce data—they do not create resources. Use them to prepare or reshape values (lists, sets, maps, strings) that you then pass into for_each, resource arguments, modules, or other expressions. They keep configurations DRY and easier to maintain.
Line-by-line explanation
  • variable block
    • variable "environments" defines a simple list: ["prod", "dev", "test"]. These are input values only; no resources are created here.
  • locals block and the for expression
    • resource_group_names = [for env in var.environments : "rg-${env}"]
    • This iterates each element in var.environments, transforms the value by prefixing rg-, and produces a new list: ["rg-prod", "rg-dev", "rg-test"].
  • resource block and for_each
    • for_each = toset(local.resource_group_names) converts the list into a set. for_each requires either a set or a map (not a plain list). Converting to a set ensures uniqueness and establishes stable keys that Terraform uses to track resources between runs.
    • Inside the resource block, each.value represents the current element from the collection (here, the resource group name) and is used as the name.
Why choose a for expression?
  • DRY configuration: Add or remove environment names in a single place and derived values update automatically.
  • Flexible transformations: Build formatted names, filter elements, or generate complex maps used later in resources or modules.
  • Separation of concerns: Locals act as a preprocessing layer—shape inputs exactly the way resources expect them.
Best practices and behavior notes
  • For expressions return a collection type (list, set, or map) depending on the syntax and context; they do not create resources.
  • Use toset() or tomap() when required by consumers like for_each so Terraform can use stable keys to track resources across runs.
  • When using a map with for_each, the map keys become resource instance keys and each.value is the corresponding value. For sets of primitive values, the element itself becomes the stable identifier used by for_each.
Do not pass a plain list directly into for_each. Always convert lists into toset() or build a map to ensure deterministic resource keys and avoid unexpected resource recreation.
Quick reference table When to use for expressions
  • Any time you need to prepare or transform input data before passing it into for_each, module inputs, or resource arguments.
  • Useful for consistent naming, filtering unwanted elements, or composing more complex structures from simple variables.
Summary
  • For expressions transform data structures—they do not create resources.
  • Locals commonly host for expressions to prepare data for resource creation.
  • for_each consumes transformed data (often after conversion to a set or map), and resources are created based on those values.
Links and references

Watch Video