ハブ記事: Terraform Modules: Complete Guide →
Hub article covering the full picture of Terraform modules: design, distribution, and operations
Terraform outputs are the official mechanism for passing values between modules and for surfacing information after a run. Even at the Associate level, declaration, reference syntax, sensitive behavior, and evaluation ordering all show up frequently.
This article covers outputs designs that survive in production and the points exam questions tend to focus on. Where version-dependent behavior is involved, we stick to current stable specifications.
An output block exposes a value computed inside a module to the outside. A parent module references it as module.<child>.output_name. Root-module outputs are shown after terraform apply and can be re-displayed with the terraform output command.
An output supports value (required), description (optional), sensitive (optional), and, when needed, depends_on (to make evaluation order explicit). Types are inferred and complex types (objects and maps) can be returned.
Minimal output configuration (child and parent)
# Child module: modules/network/outputs.tf
output "vpc_id" {
value = aws_vpc.main.id
description = "ID of the VPC that was created"
}
# Parent module: main.tf
module "network" {
source = "./modules/network"
}
output "network_vpc_id" {
value = module.network.vpc_id
}When wiring multiple modules together, the parent receives the child's outputs and re-exports them as needed. To pass values across workspaces, use the terraform_remote_state data source, but keep it loosely coupled and keep the contract (schema) stable.
Output values are finalized only after apply completes. Values that are unknown at plan time can propagate as unknown to the parent through dependency chains. Design defensively with conditionals and null-coalescing so the configuration survives an unknown.
Output flow between parent and child modules
Re-export child outputs from the parent / reference another workspace's outputs via remote_state
# Reference child outputs from the parent and re-export them
module "web" { source = "./modules/web" }
module "svc" {
source = "./modules/service"
a_id = module.web.a_id
}
output "alb_dns" {
value = module.web.alb_dns
}
output "service_url" {
value = module.svc.service_url
}
# Read outputs from another workspace (Terraform Cloud/Enterprise example)
data "terraform_remote_state" "network" {
backend = "remote"
config = {
organization = "acme"
workspaces = { name = "network-prod" }
}
}
# Example of consuming the fetched output
module "app" {
source = "./modules/app"
vpc_id = data.terraform_remote_state.network.outputs.vpc_id
}Keeping output types stable makes parent-side references less brittle. In particular, when aggregating values from child modules created with for_each, make the order and keys of maps and lists explicit.
Make order explicit for collections without a defined order using sort() or toset()/tolist(), and pin keys with tomap() on objects. Document the contract of object outputs in description with future schema expansion in mind — operations get easier.
Example: stabilize and return outputs from for_each child modules
# Group of child modules (illustrative)
module "subnet" {
source = "./modules/subnet"
for_each = {
a = { az = "ap-northeast-1a" }
c = { az = "ap-northeast-1c" }
}
az = each.value.az
}
# Return as an order-independent map
output "subnet_ids_by_key" {
value = { for k, m in module.subnet : k => m.id }
description = "Subnet IDs by key (logical names like a/c become the keys)"
}
# Return as a sorted list when order matters
output "subnet_ids_sorted" {
value = sort([for k, m in module.subnet : m.id])
description = "Subnet IDs in stable sorted order"
}
# Make the contract explicit via an object
output "network_contract" {
value = {
vpc_id = module.network.vpc_id
subnet_ids = sort([for k, m in module.subnet : m.id])
region = var.region
}
description = "Network contract exposed upward (extend by adding keys in the future)"
}Setting sensitive=true hides the value in CLI output and the UI. However, Terraform state stores the actual value, so backend encryption, RBAC, and least privilege are mandatory. Designing to avoid emitting sensitive values is the first priority; when emission is unavoidable, minimize the visibility surface.
Sensitivity propagates through expressions. Computed results that include a sensitive value automatically become sensitive, and you only strip the flag with nonsensitive() when truly needed (watch out for leaks via display and logs). In the CLI, terraform output hides sensitive outputs by default. When automation needs the value, use -json or -raw only from a secure execution environment.
| Target | Display behavior (CLI/UI) | Persisted in state | Typical use |
|---|---|---|---|
| output (sensitive=false) | Displayed in plain text | Actual value is stored | Endpoint URL, ID, DNS name, etc. |
| output (sensitive=true) | Masked or hidden by default | Actual value is stored (must be protected) | Minimal secrets (when unavoidable) |
| variable (sensitive=true) | Masked in plan/apply logs | May end up in state (when reflected on resource attributes) | Hiding input (for example, when passing an external secret) |
Choosing between sensitive and nonsensitive
# Case where the child module must return a sensitive value
output "db_password" {
value = random_password.db.result
sensitive = true
description = "DB password (masked on display)"
}
# Re-export only part of it from the parent (avoid in principle)
output "db_connection_info" {
value = {
endpoint = module.db.endpoint
username = var.db_user
// Do not emit the password; if you must, set sensitive=true
}
}
# Recompute only the publicly safe portion as non-sensitive
output "public_url" {
value = nonsensitive(module.web.public_url)
description = "Public URL (contains no secrets)"
}Normally, an output's dependencies are resolved automatically from the value expression. Occasionally, when you want to evaluate an output only after a side-effecting prerequisite is satisfied (for example, waiting for a completion signal from an auxiliary module), you can add depends_on to the output to make the order explicit.
depends_on on an output is not for changing resource creation order directly; it guarantees that output evaluation waits for a specific completion.
Example: explicitly delay output evaluation
# Emit true only after app and db both finish
output "bootstrap_complete" {
value = true
depends_on = [module.app, module.db]
description = "Completion signal for the main modules"
}
# Another example: surface the endpoint only after the secret is issued
output "service_endpoint_ready" {
value = module.svc.endpoint
depends_on = [aws_secretsmanager_secret_version.api_token]
}Renaming an output or changing its type breaks the parent module. Treat outputs as the module's public interface and keep names, types, and meaning stable. For deprecation, the safe path is to keep the old output around for a while and clearly mark it in description.
When breaking changes are unavoidable, cut a new major version tag and provide updated CHANGELOG, samples, and migration instructions for module consumers.
Example: keep a deprecated output alongside the new one
# Old: base_url is deprecated. New: use service_url
output "base_url" {
value = module.web.public_url
description = "[DEPRECATED] Use service_url instead"
}
output "service_url" {
value = module.web.public_url
description = "Public URL of the service (canonical name)"
}Associate
問題 1
The child module modules/web defines output "alb_dns". Which is the correct way to re-export this value under a different name from the root module?
正解: A
Within the same configuration, reference values as module.<child_module_name>.<output_name>. terraform_remote_state is used to read outputs from a different workspace.
What are the practical terraform output commands?
Use terraform output to list everything, terraform output name for a single value, -json for machine-readable output, and -raw name for a single value without quotes or newlines. Note that sensitive values are hidden by default.
Is it OK to put secrets in outputs?
As a rule, avoid it. If you must, set sensitive=true and enforce backend encryption and access control. Read the value only from least-privileged automation runners, and never log it.
What is the best way to reference values from another workspace?
The common pattern is to use the terraform_remote_state data source under a stable contract while keeping the producer loosely coupled. For organization-wide use, pair it with backend authorization, encryption, and version management.
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...