for_each over an object is the right tool. Both each.key (the map key) and each.value (the map value) are available inside the block, giving you access to both dimensions of each entry. Pulumi keys resources in state by each.key, which makes renames and removals predictable: changing a key destroys and recreates that resource, while changing only the value updates it in place.
What you’ll learn
- How
for_eachover an object provides botheach.keyandeach.value - The flat string map pattern — the most common form
- How Pulumi uses
each.keyto track resources in state
Why this matters
Objects give you named, independently-addressable resources. Each
each.key becomes a distinct Pulumi resource identity in state — you can remove one entry from the map without affecting the others, unlike list-based for_each where index shifts can cause unexpected destroys.The source code
How it works
The object is resolved at compile time
The object literal is
Resolved<T> — all keys and values are known at compile time. ubx expands it into one IRUnit node per entry in the IR pass.each.key and each.value are substituted per entry
For the buckets block: first iteration gives
each.key = "assets", each.value = "primary"; second gives "logs" / "archive"; and so on. Both are available anywhere inside the block body.What ubx generates
Common mistakes
Run it
What you learned
for_each over an object provides each.key (the map key) and each.value (the map value)Pulumi keys resources by
each.key — removing an entry destroys only that resourceFlat string maps are the most portable pattern in ubx v1
Next steps
count meta-argument
Create N copies of a resource by number
when conditional resource
Conditionally create or skip a resource entirely
Full runnable example: github.com/ubiquex/ubx-examples/07-for-each-object

