A splat expression is Terraform syntax for pulling a specific attribute out of every element of a list or other collection at once. The typical use case is bulk-fetching IDs from multiple instances, e.g., aws_instance.web[*].id.
Since Terraform 0.12, the recommended approach is full splat ([*]) plus for expressions rather than legacy splat (.*.). This article sticks to stable behavior and covers both the implementation and exam angles based on the official documentation.
Splat expressions extract per-element attribute values from indexable collections (mainly lists/tuples, sets, and map/objects converted to values). The classic case is pulling attributes out of resources or modules created with count or for_each.
Since Terraform 0.12, full splat [*] is the first choice. Legacy splat .*. remains for compatibility, but you should avoid it in new code. Use a for expression ([for v in xs : v.attr]) when you also need to filter or transform.
Visualizing a splat expression
Input (list of objects)
[
{ id: "i-001", name: "app-a" },
{ id: "i-002", name: "app-b" },
{ id: "i-003", name: "app-c" }
]
|
| apply [*].id
v
[ "i-001", "i-002", "i-003" ] ← only the id attribute, extracted in bulkMinimal full splat example
variable "instances" {
type = list(object({ id = string, name = string }))
}
locals {
ids = var.instances[*].id
names = var.instances[*].name
}
output "ids" {
value = local.ids
}
Splat behavior depends on the target collection type. Lists/tuples preserve definition order. Sets have no order, so the result order is undefined. Maps/objects depend on key order, but a direct splat on them does not always make that order explicit.
Resources or modules created via for_each become objects (a keyed collection). If you need a list with stable order, convert to a value list with values(...). values(map) corresponds to the lexical order of keys(map), so the result is stable.
Getting IDs in stable order from a for_each resource
resource "aws_instance" "web" {
for_each = { a = "10.0.0.10", c = "10.0.0.12", b = "10.0.0.11" }
ami = "ami-12345678"
instance_type = "t3.micro"
private_ip = each.value
}
# Stable IDs (lexical key order: a, b, c)
locals {
web_ids = values(aws_instance.web)[*].id
}
output "web_ids" {
value = local.web_ids
}
For simple attribute extraction, splat is concise. When you also want conditional extraction or transformation, a for expression fits better. Legacy splat (.*.) is discouraged for readability and future-proofing reasons.
Associate exam questions often check whether you understand the equivalent forms (xs[*].attr vs. [for x in xs : x.attr]), whether values() is needed to get a stable-order list from a map/object, and whether filtering is required.
| Approach | Example | Strengths / Caveats |
|---|---|---|
| full splat([*]) | instances[*].id | Shortest and most readable. No filtering. Stable order on lists/tuples. Combine with values() for maps/objects when needed. |
| legacy splat(.*.) | instances.*.id | Kept for backward compatibility. Not recommended for new code; some teams explicitly forbid it in style guides. |
| for expression | [for i in instances : upper(i.name) if i.enabled] | Flexible: extraction, transformation, and conditions in one shot. Slightly verbose. Order follows the input. |
Equivalent forms and a filtered example
locals {
# Equivalent: simple extraction
ids_via_splat = aws_instance.web[*].id
ids_via_for = [for r in aws_instance.web : r.id]
# Transformation + condition: for expression is the right tool
names_upper_enabled = [
for r in aws_instance.web : upper(r.tags["Name"]) if try(r.tags["enabled"], "false") == "true"
]
}
When you invoke a module multiple times with count or for_each, module.<NAME> becomes a collection. You can collect outputs in bulk with a splat like module.db[*].endpoint. For for_each, values(module.db)[*].endpoint makes the order explicit.
When you combine nested splats and for expressions, normalizing and absorbing edge cases with functions like flatten, compact, try, and coalesce keeps things robust.
Safely collecting module outputs
module "db" {
source = "./modules/db"
for_each = { a = {}, b = {}, c = {} }
}
# Endpoint list in stable order
locals {
db_endpoints = values(module.db)[*].endpoint
# Nested: assume each DB module returns multiple replica endpoints
# module.db[each].replicas is list(string)
replica_lists = values(module.db)[*].replicas
all_replicas = flatten(local.replica_lists)
# Resilient to missing values (some modules may have null replicas)
safe_all_replicas = flatten([for m in values(module.db) : coalesce(m.replicas, [])])
}
output "db_endpoints" {
value = local.db_endpoints
}
When inputs contain values that are unknown at plan time or are null, the splat result can include unknown or null entries. Passing that straight into other computations can cause type mismatches or surprise diffs, so it is safer to normalize early with try, compact, and coalesce.
Splats over sets or objects tend to leave the order undefined. When you need a stable order, pin it explicitly with values(...) or a for expression driven by sort(keys(...)).
Robustness snippet collection
# 1) Allow splat even when input is null by defaulting to an empty list
locals {
safe_ids = coalesce(var.maybe_items, [])[*].id
}
# 2) Suppress evaluation-time errors
locals {
try_ids = try(aws_instance.web[*].id, [])
}
# 3) Stable-order extraction from an object (ascending keys)
locals {
ids_ordered = [for k in sort(keys(aws_instance.web)) : aws_instance.web[k].id]
}
A small example that filters private subnets in a VPC by tag and produces a list of IDs. Extraction is done with splat, filtering with a for expression, and the final result is an ID-only array.
For the Associate exam, it is enough to be solid on choosing between splat and for expressions, stabilizing order with values(), and the basics of compact/flatten.
Subnet ID extraction sample
data "aws_subnets" "selected" {
tags = {
Tier = "private"
}
}
# data.aws_subnets.selected.ids is a set(string)
# If order matters, combine tolist() + sort() (strings only)
locals {
subnet_ids_unsorted = data.aws_subnets.selected.ids
subnet_ids_sorted = sort(tolist(local.subnet_ids_unsorted))
# To layer in extra conditions (e.g., only /24 CIDRs), use a for expression
# Example assumes data.aws_subnet.this[*] has the necessary attributes — adapt to your real data reference
# ids_only = [for s in values(data.aws_subnet.this) : s.id if can(regex("/24
NicheeLab を読み込み中…
quot;, s.cidr_block))] } output "subnet_ids_sorted" { value = local.subnet_ids_sorted }
Associate
問題 1
You want a list of instance IDs from aws_instance.web (created via for_each) in ascending key order (a → z). Which is the most concise, recommended expression?
正解: A
The result of for_each is an object. values(obj) returns a stable list corresponding to the lexical order of keys(obj), so values(aws_instance.web)[*].id is both concise and order-guaranteed. B and C do not make the order explicit, and D is legacy splat which is not recommended for new code.
Is legacy splat (.*.) something I should stop using?
It still works for compatibility, but since Terraform 0.12 full splat ([*]) and for expressions are the recommended form. Many team style guides avoid .*., and the exam questions are written assuming [*] or for expressions.
How can I get values in a stable order from for_each resources or modules?
Convert to a value list with values(...) and then splat. For example, values(aws_instance.web)[*].id or values(module.app)[*].endpoint produces results ordered by the lexical order of the keys.
What should I watch out for with sets or unknown values?
Sets have no order, so use tolist()+sort() when you need ordering (sort only works on string lists). When unknown values or nulls may appear at plan time, normalize early with try(..., []), coalesce(..., []), or compact() to stay safe.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
HCL Syntax: Terraform's Configuration Language (2026)
HCL2 fundamentals for Terraform — blocks, attributes, expres...
Terraform Authoring & Operations Pro: Complete Guide (2026)
Tactics for the Terraform Pro exam — module authoring, works...
Terraform Providers: Plugin Management Fundamentals (2026)
Provider mechanics — required_providers, versions, mirrors, ...
Terraform Resource Blocks: Declarative Infra Units (2026)
Resource block fundamentals — addresses, references, common ...
Terraform Data Sources: Read-Only External Data (2026)
Data source basics — declaration, refresh behavior, dependen...