> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ubiquex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# for_each over a List

> Create multiple resources from a list — one resource per list element.

When you need the same type of resource with slightly different names or configs — three S3 buckets for different purposes, four subnets across availability zones, a set of SSM parameters — writing a separate `unit` block for each is repetitive and brittle. Add one more bucket to the list and you have to add another block. `for_each` over a list solves this: ubx creates one resource per element, making the list the authoritative source of what gets provisioned. The current element is always available as `each.value`, and the resource label becomes the iteration key in the generated Pulumi state. The result is a concise declaration that scales from two resources to twenty without touching the block definition.

## What you'll learn

* How `for_each` over a list creates one resource per element
* How to use `each.value` to reference the current element
* How Pulumi keys the generated resources in state

***

## Why this matters

<Info>
  With `for_each`, your list is the single source of truth. Adding or removing an element automatically provisions or destroys the corresponding resource on the next `ubx apply` — no block duplication, no manual bookkeeping.
</Info>

***

## The source code

<CodeGroup>
  ```hcl main.iac theme={"theme":"css-variables"}
  # for_each over a list — creates one resource per item.
  # each.value is the current list element.
  unit "aws_s3_bucket_v2" "bucket" {
    for_each = ["assets", "logs", "uploads", "backups"]
    bucket   = "${input.env}-${each.value}"

    tags = {
      Name    = "${input.env}-${each.value}"
      Purpose = each.value
      Env     = input.env
    }
  }
  ```

  ```hcl inputs.iac theme={"theme":"css-variables"}
  input "env" {
    type    = "string"
    default = "dev"
  }
  ```

  ```hcl outputs.iac theme={"theme":"css-variables"}
  output "env" {
    value = input.env
  }
  ```

  ```hcl ubx.iac theme={"theme":"css-variables"}
  ubx {
    name    = "for-each-list"
    runtime = "typescript"
    stacks  = ["dev", "staging", "prod"]
  }

  backend "local" {
    path = ".ubx/state"
  }
  ```
</CodeGroup>

***

## How it works

<Steps>
  <Step title="The for_each list is resolved at compile time">
    The list `["assets", "logs", "uploads", "backups"]` is `Resolved<T>` — it's a literal known at compile time. ubx expands it into four `IRUnit` nodes in the IR pass, one per element.
  </Step>

  <Step title="each.value is substituted per iteration">
    In each expanded node, `each.value` is replaced with the corresponding list element: `"assets"`, `"logs"`, `"uploads"`, `"backups"`. The bucket name and tag values are computed for each iteration.
  </Step>

  <Step title="Pulumi keys resources by label and index">
    The generated code creates four separate `BucketV2` instances. Pulumi tracks each one in state using the resource label (`bucket`) combined with the element value as the key — so a rename in the list triggers a destroy and recreate, not an in-place update.
  </Step>
</Steps>

***

## What ubx generates

<CodeGroup>
  ```typescript index.ts theme={"theme":"css-variables"}
  // Generated by ubx — do not edit
  import * as pulumi from "@pulumi/pulumi";
  import * as aws from "@pulumi/aws";

  const config = new pulumi.Config();
  const env = config.get("env") || "dev";

  const bucketList = ["assets", "logs", "uploads", "backups"];
  const buckets = Object.fromEntries(
      bucketList.map(item => [item, new aws.s3.BucketV2(`bucket-${item}`, {
          bucket: `${env}-${item}`,
          tags: { Name: `${env}-${item}`, Purpose: item, Env: env },
      })])
  );

  export const envOut = env;
  ```

  ```python __main__.py theme={"theme":"css-variables"}
  # Generated by ubx — do not edit
  import pulumi
  import pulumi_aws as aws

  config = pulumi.Config()
  env = config.get("env") or "dev"

  bucket_list = ["assets", "logs", "uploads", "backups"]
  buckets = {
      item: aws.s3.BucketV2(f"bucket-{item}",
          bucket=f"{env}-{item}",
          tags={"Name": f"{env}-{item}", "Purpose": item, "Env": env},
      )
      for item in bucket_list
  }

  pulumi.export("env", env)
  ```

  ```go main.go theme={"theme":"css-variables"}
  // Generated by ubx — do not edit
  package main

  import (
      "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/s3"
      "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
      "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
  )

  func main() {
      pulumi.Run(func(ctx *pulumi.Context) error {
          cfg := config.New(ctx, "")
          env := cfg.Get("env")
          if env == "" {
              env = "dev"
          }

          for _, item := range []string{"assets", "logs", "uploads", "backups"} {
              _, err := s3.NewBucketV2(ctx, "bucket-"+item, &s3.BucketV2Args{
                  Bucket: pulumi.Sprintf("%s-%s", env, item),
                  Tags: pulumi.StringMap{
                      "Name":    pulumi.Sprintf("%s-%s", env, item),
                      "Purpose": pulumi.String(item),
                      "Env":     pulumi.String(env),
                  },
              })
              if err != nil {
                  return err
              }
          }

          ctx.Export("env", pulumi.String(env))
          return nil
      })
  }
  ```
</CodeGroup>

***

## Common mistakes

<Warning>
  Renaming an element in the `for_each` list is a destroy-and-recreate, not a rename. Pulumi keys resources by the element value — changing `"assets"` to `"static"` means destroying the assets bucket and creating a new static bucket. Use the `moved` block if you need to rename without destroying.
</Warning>

<Tip>
  `for_each` over a list works best when all elements are the same "shape" — the same attributes with the element value substituted in. If different elements need significantly different configurations, consider separate `unit` blocks with `when` conditions, or `for_each` over an object with richer per-key values.
</Tip>

***

## Run it

```bash theme={"theme":"css-variables"}
ubx validate
ubx plan             # creates 4 buckets
ubx plan --var env=prod
```

***

## What you learned

<Check>`for_each` over a list creates one resource per element, with `each.value` as the current item</Check>
<Check>The list is the authoritative source — add or remove elements to provision or destroy resources</Check>
<Check>Renaming a list element triggers destroy-and-recreate; use `moved` for safe renames</Check>

***

## Next steps

<CardGroup cols={2}>
  <Card title="for_each over an object" href="/v1/tutorials/07-for-each-object">
    Use each.key and each.value with a map
  </Card>

  <Card title="count meta-argument" href="/v1/tutorials/08-count-meta-argument">
    Create N copies of a resource by number
  </Card>
</CardGroup>

***

<Info>
  Full runnable example: [github.com/ubiquex/ubx-examples/06-for-each-list](https://github.com/ubiquex/ubx-examples/tree/main/06-for-each-list)
</Info>
