Skip to main content
RunBook Academy

TerraformV · The Terraform WorkflowProduction Terraform

terraform output and terraform show

Foundation⏱ ~10 minbash

What you'll learn

  • Read state values with terraform output in human-readable, raw, and JSON forms
  • Use terraform show to inspect a plan file, current state, or a saved configuration
  • Hand values between pipeline stages using terraform output -json and downstream consumers
  • Treat sensitive outputs with the correct redaction and exposure discipline
  • Choose between terraform output and terraform show for the inspection task at hand

Prerequisites

Verified against Terraform CLI 1.9.x · OpenTofu 1.7.x · HCL 2.0 · bpg/proxmox provider 0.66+ · hashicorp/local provider 2.5+ · hashicorp/null provider 3.2+ · hashicorp/random provider 3.6+ · hashicorp/http provider 3.4+ · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · 2026-08-13

Not yet marked complete on this device.

Two commands in the workflow exist to inspect what Terraform knows. terraform output reads the values declared as outputs in the configuration. terraform show reads the state, the most recent plan, or a saved plan file. Both are read-only. Both are essential for handing values between stages of a pipeline.

What output does

The output block in HCL declares a value to expose:

output "vpc_id" {
  value       = aws_vpc.main.id
  description = "The ID of the primary VPC"
}

output "db_endpoint" {
  value       = aws_db_instance.primary.address
  description = "Connection endpoint for the primary database"
  sensitive   = true
}

After apply, Terraform stores the resolved value in the state file. The CLI commands read from state, not from configuration. If the state is missing or the apply has not run, terraform output errors with “No outputs found” or a similar message.

The CLI forms:

# List all outputs in human-readable form.
terraform output

# Print a single output's value.
terraform output vpc_id

# Print a single output as a raw string (no quotes, no escaping).
# Suitable for piping into another command.
terraform output -raw db_endpoint

# Emit all outputs as a JSON object on stdout.
terraform output -json

# Emit a single output's value as a JSON scalar.
terraform output -json vpc_id

Sample output:

$ terraform output
db_endpoint = (sensitive value)
vpc_id = "vpc-0abc123def456789"

$ terraform output vpc_id
"vpc-0abc123def456789"

$ terraform output -raw vpc_id
vpc-0abc123def456789

$ terraform output -json
{
  "db_endpoint": {
    "sensitive": true,
    "type": "string",
    "value": "primary.xxxxx.us-east-1.rds.amazonaws.com"
  },
  "vpc_id": {
    "sensitive": false,
    "type": "string",
    "value": "vpc-0abc123def456789"
  }
}

The four forms serve four use cases:

  • Default (terraform output): human inspection. Sensitive values are redacted as (sensitive value).
  • Single value (terraform output vpc_id): human inspection of one value.
  • Raw (-raw): pipe into a command. Useful in shell pipelines where quotes are noise.
  • JSON (-json): machine-readable. The whole outputs map, including sensitive values, exposed as a JSON object.

What show does

terraform show reads a state or plan file and prints it in human-readable form. The argument determines what is shown:

# Default: show the current state in human-readable form.
terraform show

# Show the current state as JSON.
terraform show -json

# Show a saved plan file in human-readable form.
terraform show tfplan

# Show a saved plan file as JSON (used by Atlantis, Spacelift).
terraform show -json tfplan

Sample output:

$ terraform show tfplan
# aws_instance.web will be created
+ resource "aws_instance" "web" {
    + ami           = "ami-0a1b2c3d4e5f"
    + instance_type = "t3.small"
    ...
  }

Plan: 1 to add, 0 to change, 0 to destroy.

terraform show is broader than terraform output:

CommandReads fromScope
terraform outputStateOnly declared output blocks
terraform showState or plan fileEvery resource, every attribute, plus plan diff

Use output when you have a named value the configuration exposes (a database endpoint, a load balancer DNS name, a VPC ID). Use show when you need to inspect a resource that is not declared as an output, or when you need to render a plan file.

The pipeline handoff pattern

The standard pattern for handing a Terraform-managed value to the next stage of a pipeline:

# Stage 1: terraform apply, which updates state with the new value.
terraform apply -input=false -auto-approve tfplan

# Stage 2: read the value out of state and pass it to the next step.
DB_ENDPOINT=$(terraform output -raw db_endpoint)

# Stage 3: use the value in a subsequent command.
ansible-playbook -e "db_endpoint=${DB_ENDPOINT}" deploy_app.yml

The pattern works because -raw strips quotes and produces a clean string. Without -raw, the value comes out as "primary.xxxxx.us-east-1.rds.amazonaws.com" (with literal quotes), which breaks most shell interpolations.

For values that are not strings (lists, maps), use -json and parse with jq:

# Get a list of subnet IDs as a JSON array, then pass to a tool that
# expects JSON.
terraform output -json subnet_ids | jq -c '.value'

# Get a map of tags and merge into an Ansible vars file.
terraform output -json instance_tags | jq '.value' > instance_tags.json

Sensitive output discipline

An output marked sensitive = true is redacted by the human-readable output forms. The JSON form reveals it. The discipline:

  • Default to sensitive = true for any value that could be a secret: passwords, tokens, ARNs that grant access, private keys, database endpoints (because they reveal infrastructure).
  • Do not pipe -json to a chat channel, a wiki, or a public artefact store.
  • If a downstream stage needs the sensitive value, pass it through an environment variable or a secret store, not through a log line.
  • Treat the state file as a secrets document. The state backend should have encryption at rest and tight IAM.

A common incident: an operator runs terraform output -json > outputs.json for debugging, then cat outputs.json to inspect it. The terminal log records every sensitive value. The terminal log is backed up to a SaaS that does not have the same access controls as the state backend.

When the state is empty

terraform output fails when there are no outputs in state:

$ terraform output
No outputs found

This happens when:

  • Apply has not run yet. State is empty.
  • The configuration was modified to remove all output blocks. State still has them; plan shows them being destroyed on the next apply.
  • The state file is from a different working directory or backend. Cross-check with terraform state list.

Run terraform plan first. An empty state surfaces in plan as “nothing to do” or as resources to be created. After apply, terraform output will return values.

Production failure modes

1. Output used by a downstream stage before apply has run. Symptom: a deployment script that reads terraform output db_endpoint fails because the state has no outputs yet. Cause: the pipeline ran apply in the wrong order, or the deployment job ran before the infrastructure job. Recovery: enforce pipeline ordering. The infrastructure job must complete before the deployment job. Use terraform output after the apply step, not before.

2. -json output containing sensitive values posted to a public channel. Symptom: a database password appears in a Slack channel or a public artefact. Cause: the operator piped -json to a chat command or to a debug log that is mirrored to a less-protected store. Recovery: rotate the credential. Add the sensitive flag to the output. Restrict who can read the channel. Do not store the JSON output as a long-lived artefact.

3. Stale output value consumed after state has changed. Symptom: the deployment script uses a stale database endpoint; connection fails. Cause: the infrastructure was updated, but the downstream job ran against a cached or older terraform output value. Recovery: always run terraform output immediately before the downstream stage, not from a cached file. If the value is cached across deploys, the cache becomes a source of drift.

4. Sensitive output with -json parsed and printed by a script. Symptom: a CI script that wraps terraform output -json to extract a value then prints the value to the job log. Cause: the script does not honour the sensitive flag. Recovery: the script should redact sensitive values before printing, or read only the specific named output via terraform output -json <name> and pipe directly to the next stage without printing.

5. Output value depends on a resource that was recreated by a -replace. Symptom: the output references a resource that was destroyed and recreated by an apply. The output now reflects the new resource, but downstream services (DNS, load balancers, secrets stores) still reference the old one. Cause: outputs are a snapshot at the end of apply; downstream services need their own update. Recovery: this is not a Terraform failure. It is a downstream propagation problem. Coordinate the downstream update with the Terraform apply.

6. terraform show on a plan file from a different environment. Symptom: terraform show tfplan shows changes that look reasonable, but they are for the staging environment while the operator is reviewing in production. Cause: shared artefact storage across environments; wrong file downloaded. Recovery: prefix plan files with the environment (prod-tfplan, staging-tfplan); use environment-specific artefact stores; require human approval for production plan review.

Security implications

Outputs are the boundary between Terraform state and the rest of the world. Anything declared in an output block is, by definition, exposed to whatever process runs terraform output. The discipline:

  • An output that does not need to be exposed to other tools should not be declared.
  • An output that needs to be exposed only to specific tools should be marked sensitive = true to prevent accidental logging.
  • The state backend should treat outputs as secrets: encryption at rest, audit logging on read.

The state file contains every output value, sensitive or not. A read of the state file from the backend reveals everything. Lock down the bucket.

Performance implications

terraform output reads the state file from the backend. For a remote backend (S3, GCS, Terraform Cloud), this is one network call. For a local state file, it is a disk read. Both are fast. The same applies to terraform show -json on the current state.

terraform show tfplan reads a local plan file. No network call. Fast.

Verification

# List outputs and confirm sensitive values are redacted.
terraform output
# Expect: db_endpoint = (sensitive value)

# Confirm the JSON form contains the sensitive value (for the runbook).
terraform output -json db_endpoint | jq '.value'
# Use this output in a secret store, never in a log.

# Confirm terraform show reads the plan file.
terraform show tfplan | head -50
# Expect: the plan diff, including all the "will be created" symbols.

A healthy output workflow leaves sensitive values in the state, exposes them only via -raw or -json to the specific downstream stage that needs them, and never prints them to a log.

What comes next

The next lesson covers terraform console — the interactive REPL for evaluating HCL expressions against current state. It is the right tool for debugging complex expressions, but it is not a substitute for running plan.

Knowledge check · 7 questions

  1. Q1. Which command prints a single output value as a raw string with no quotes, suitable for shell interpolation?

  2. Q2. terraform output -json redacts sensitive values, just like the human-readable form.

  3. Q3. What is the difference between terraform output and terraform show?

  4. Q4. Which of the following are appropriate uses of terraform output in a CI pipeline? (Select all that apply.)

  5. Q5. A deployment script reads terraform output db_endpoint at the start of the pipeline and stores it in a variable. Three hours later, it uses the variable to connect to the database. The connection fails. What is the most likely cause?

  6. Q6. Which command renders a saved plan file in human-readable form?

  7. Q7. An output block is declared with sensitive = true. A team member runs terraform output -json sensitive_secret to extract the value for a one-off script. They paste the output into a Slack DM to share with a teammate. What is the security impact and the immediate remediation?

Passing score: 75%. Answers are checked in this browser.