Terraform State Show: What It Shows and What It Doesn't
terraform state show is the right command for inspecting a single resource's attributes, and useful for engineers. But there are questions it cannot answer, meaning that attribute-level inspection and relationship-level inspection are different problems requiring different tools.
terraform state show prints the current attributes of one resource from the state file, scoped to a single address.-json flag.-json – this requires careful handling.terraform state show reads state rather than running a plan, so it is fast and reflects what Terraform last recorded rather than interrogating cloud APIs directly. For machine-readable output, the supported path is terraform show -json, which produces a documented JSON format for state or plan files.
The command answers one question well. What does this resource look like in state right now? Everything else – dependencies, downstream blast radius, drift, cross-state relationships – sits outside what it was designed to do.
What terraform state show does
terraform state show shows the last known attributes of a single resource in Terraform state, identified by its resource address. It belongs in every Terraform engineer’s toolkit because it answers a common, practical question.
You have a resource address, you want to inspect the attributes Terraform has recorded for that resource, and you do not want to run terraform plan, refresh a provider, or dig through a raw terraform state file by hand.
It’s useful during imports, debugging sessions, post apply checks, and the quiet little moments when the plan output has scrolled away and someone asks which AMI, subnet, private IP, database identifier, or generated name Terraform thinks it created.
However, its narrowness means it has a ceiling. terraform state show reads one state, one workspace, one address. It does not build the dependency graph, it does not infer blast radius, and it does not tell you whether downstream infrastructure is broken because a relationship changed while every attribute on the resource you inspected still looks fine.
Essentially, attribute inspection and relationship inspection are different problems.
terraform state show reads one state record
The basic command shape is simple.
For a root module resource, the address usually follows the form resource_type.resource_name, which is why a resource block like this becomes aws_instance.web after apply.
In Terraform addresses, a root module resource is identified by its resource type and local name, as in aws_instance.web, while resources inside modules add the module path before that resource address, as in module.web.aws_instance.this.
The terraform state show command output is for human consumption, not programmatic consumption, meaning it’s easy to read.
It resembles HCL resource syntax rather than the raw JSON format of the underlying state file, making it much easier to inspect resources from a terminal while you are debugging.
Module resources are just longer addresses
A module resource uses the same pattern, with the module path added before the resource spec. If the resource lives inside module.web, the address becomes module.web.aws_instance.this.
Deeply nested modules extend the chain in the same way. A resource inside module.platform, then inside module.compute, would look like this.
This is not special syntax for state show, it is Terraform’s resource addressing model. The module path identifies the module tree, the resource spec identifies the specific resource, and indexes appear when count or for_each creates multiple instances.
For resources created with count, the address includes a numeric index, as in aws_instance.web[3]; for resources created with for_each, it includes the instance key, as in aws_instance.web["example"]. Brackets and string keys often need careful quoting in the shell.
In shells, quote addresses with special characters.
That quoting habit saves time, especially when the address includes a for_each key, a module index, or anything else your shell might try to interpret before Terraform sees it.
Remote state still means one state
For a local backend, terraform state show defaults to terraform.tfstate, and the documented -state=path option lets you point at an alternate local state file. That option is a legacy option for the local backend only.
For remote state storage, the state subcommands work against the configured backend. The CLI still uses the backend block and selected workspace to decide which state it reads, and state subcommands work with remote state as if it were local, with network round trips added for reads and writes.
You get convenience, but you also hit a boundary. The command reads one backend, one workspace, one state. It will not look across another state file because a downstream service uses your VPC ID through remote state, and it will not infer that a resource in a separate root module is operationally coupled to the one you are inspecting.
terraform state show vs. terraform show
A useful terraform state show command reference has to be blunt about the flags, because this is where a lot of search results blur terraform state show and terraform show.
-state=path is documented for terraform state show, and it points Terraform at an alternate local state file path. It defaults to terraform.tfstate for the local backend and is marked as a legacy local backend option.
-json is not documented for terraform state show. If you need machine-readable output, use terraform show -json against the current state, a local state file, or a saved plan file, then filter the JSON to the resource you care about.
terraform state show output is for humans, while software should use terraform show -json with the documented structure.
-no-color is documented for terraform show, not for terraform state show in the current command page. For CI output and log parsing, the safer automation path is still terraform show -json, as JSON is a contract and colored HCL-style text is not.
| Question | terraform state show |
terraform show |
|---|---|---|
| Scope | Shows one resource from Terraform state | Shows the whole current state or a saved plan file |
| Required input | Requires a resource address, such as aws_instance.web |
Does not require an address |
| Best for | Inspecting the last known attributes of a specific resource | Reviewing broader state, planned operations, or machine-readable output |
| JSON support | Not documented for this command | Supports -json for state or plan output |
| Automation fit | Better for interactive inspection | Better for scripts, CI, audits, and parsing |
| Common confusion | Often searched as terraform show state when the user wants one resource |
Often used when the user wants a whole state or plan view |
The JSON path belongs to terraform show
If you want to use terraform state show json, the accurate command is usually this.
Or, when you have a saved plan file from terraform plan -out=tfplan.
For state output, Terraform’s JSON format uses a top-level object with values and terraform_version, and the values representation contains root_module, resources, and nested child_modules.
A resource object includes fields such as address, mode, type, name, provider_name, schema_version, values, and sensitive_values, which is the structure you can pipe into jq, feed into audit scripts, or cross-reference with other tooling.
A representative state fragment looks like this.
It is not as quick to read as terraform state show aws_instance.web, but it is the right surface for automation. Human-readable output is for humans. Machine-readable output is for machines.
Sensitive values are a state security problem, not just an output problem
The searched phrase terraform state show sensitive value usually comes from a real debugging moment. Terraform shows (sensitive value) for an attribute, and the engineer wants to know whether the secret exists in state, whether it can be printed, and whether JSON changes the risk.
Terraform’s sensitivity model is conservative in CLI output intended for humans. Provider developers can mark resource attributes as sensitive, and Terraform will show a placeholder rather than the actual value in human-readable output.
However, Terraform still records sensitive values in state, which means anyone who can access the state data may be able to access those values in cleartext.
Remember that redaction in the terminal is not encryption in the state file. When you use terraform show -json, sensitive values can appear in plain text, so do not pipe JSON state output into shared CI logs, paste it into tickets, or store it unredacted in audit artifacts. If automation needs it, redact fields before output and treat the resulting file like state itself.
The right use cases are attribute questions
terraform state show is strongest when you already know the resource address and need to inspect the current state for that specific resource. After an import, it can confirm that Terraform attached the real cloud object to the destination address you intended, and that the recorded ID, tags, name, ARN, or provider-assigned attributes match the thing you meant to bring under management.
It is also useful after terraform apply, when computed values that did not exist at plan time become important. Public IPs, generated names, security group IDs, route table IDs, and provider-assigned identifiers often matter only after creation, and terraform state show gives you the current state Terraform recorded without requiring a new plan.
It helps when you are comparing state with reality, as long as you remember what is being compared. terraform state show aws_instance.web can tell you what Terraform thinks the AMI, instance type, and network attributes are. It cannot prove the live cloud object still matches. For that, you need a refresh, a plan, or a direct provider inspection.
What terraform state show can't tell you
The ceiling appears when the question changes from what this resource is to what this resource affects.
terraform state show aws_security_group.api can show
- The recorded ingress rules
- Egress rules
- Tags
- IDs
- Provider attributes for that security group.
It cannot:
- Show which instances, load balancers, modules, or separate states rely on it
- Tell you the blast radius of modifying a rule
- Tell you that another state consumes its ID through a remote state output and will fail after your change
The same failure mode shows up with subnets. A subnet’s attributes can look correct, while the outage is still relational because an autoscaling group, database subnet group, route, NAT gateway, or security boundary depends on how that subnet connects to the rest of the graph.
Drift is another boundary. terraform state show reads Terraform’s recorded state. It does not ask the provider API whether the live object still matches. Cross-state relationships sit outside the command, too. If one state owns networking and another owns compute, terraform state show cannot follow the operational dependency from one file to the next.
Relationship debugging needs a graph that survives the run
Terraform does have a graph. It builds one during plan and apply so it can order operations, resolve dependencies, and parallelize work. The important detail is that the graph is reconstructed for the run and then discarded.
Our framing in the Terraform has a graph blog is that Terraform’s graph is ephemeral, while Stategraph persists the graph and makes it queryable infrastructure rather than a private execution detail.
That is the model shift. terraform state show can inspect the attributes of a single resource. A persistent graph can answer what depends on that resource, which states are connected through it, what the minimal impacted subgraph is, and what a change might affect before it ships.
Stategraph replaces the flat JSON file with a structured database, imports existing state, keeps Terraform and OpenTofu workflows familiar, and makes resources queryable from day one. That gives teams blast radius analysis, dependency graph visibility, multi-state operations, drift detection, and Terraform CLI compatibility without changing how engineers write Terraform.
Read the Stategraph docs for more information.
The ceiling is not a flaw
terraform state show is a well-designed, focused command. It shows the attributes of a single resource in Terraform state quickly and predictably, without pretending to be a planner, drift detector, graph explorer, or cross-state dependency system.
The ceiling it hits is the ceiling of the flat file, single resource inspection. When debugging moves from attributes to relationships, from one resource to blast radius, from one local state file to remote state storage and cross-state dependencies, a different model is needed.
Stategraph exists for that relational layer. It keeps the way engineers write Terraform, but changes what state can be underneath it. Start with Stategraph for free and see how it can accelerate your infrastructure.
terraform state show FAQs
How do I use terraform state show on a resource inside a module?
Use the module path before the resource spec, as in terraform state show module.web.aws_instance.this.
For nested modules, keep extending the path, as in module.platform.module.compute.aws_instance.web. If count or for_each is involved, include the instance index or key and quote the full address in your shell.
Why does terraform state show display (sensitive value) for some attributes?
Terraform displays (sensitive value) when a value is marked sensitive for CLI rendering, but that does not mean the value is absent from state. Sensitive values can still be stored in the state file, so state access is security access.
Can I use terraform state show against a remote backend?
Yes, terraform state show works with remote state through the backend configured for the working directory and selected workspace. The command still reads one state, so it will not follow dependencies into other state files or other workspaces.