Visibility

When state is a file, every question is a grep.

Stategraph stores state as a normalized graph in Postgres. What you have, what a change touches, what it costs, and who changed it last are queries, not files you parse.

Queryable state Blast radius across states Append-only history

What you can see

Questions a flat file cannot answer

Query

Ask the state directly

A state file is JSON you grep. Stategraph keeps every resource, attribute, and dependency edge in Postgres tables, and you query them with SQL.

Inventory →
stategraph · sql
❯ stategraph sql schema resources(type,name,provider,module,…) instances(address,attributes,dependencies,…) states(name,workspace,created_at,…) providers cost_snapshots ❯ stategraph query "SELECT type, COUNT(*) FROM resources GROUP BY type ORDER BY COUNT(*) DESC LIMIT 5" type count kubernetes_role_binding 586 kubernetes_manifest 382 null_resource 317 kubernetes_service 175 google_kms_key_ring 166 ❯ stategraph query "SELECT COUNT(*) FROM instances" count 7190

Real output captured from a live Stategraph instance.

Blast radius

What a change touches

A plan lists what you changed, not what it breaks. Stategraph walks the dependency graph and lists every dependent by distance, remote-state consumers in other states included.

Blast radius →
stategraph · blast-radius
❯ stategraph blast-radius \ "module.scrum.data.google_compute_network.shared_network_dev" DISTANCE RESOURCE 0 module.scrum.data.google_compute_network.shared_network_dev 1 module.scrum.google_redis_instance.agent_sandbox 1 module.scrum.google_redis_instance.memorystore_jobs 1 module.scrum.google_memcache_instance.memorystore 1 module.scrum.google_redis_instance.memorystore_v2

distance 0 = the changed resource · distance 1 = directly affected dependents

Cost

What it costs, in the plan

A plan shows the diff, not the bill. Every Stategraph plan carries current versus planned cost, per state and per resource, so the reviewer sees both together.

Cost →
stategraph · plan
❯ stategraph plan --out plan.json Plan: 1 to add, 2 to change, 0 to destroy. Costs: Totals: Monthly: 130.82 USD → 140.16 USD (+9.34 USD) Hourly: 0.18 USD → 0.19 USD (+0.01 USD) Resources: 14 → 15 (+1) Coverage: 100.0% (unchanged) Per state: prod-network: +9.34/mo (resources +1) + aws_nat_gateway.main +9.34

current → planned, with the delta in green.

History

What happened, and who did it

Terraform state is one overwritten snapshot with no record of who applied what. Stategraph writes every apply as an append-only transaction, attributed to a user and queryable in SQL.

Audit timeline →
stategraph · tx
❯ stategraph tx list --tenant 7b2e1f44-… { "results": [ { "id": "102881bb-686b-49a0-a0ff-fce0ab3050ea", "created_at": "2026-06-08T19:35:57Z", "created_by": "f6eca568-3097-442c-bfe0-6b3593407feb", "state": "open", "params": {}, "tags": {} }, { "id": "…", "created_at": "2026-06-08T19:35:44Z", "completed_at": "2026-06-08T19:35:44Z", "created_by": "f6eca568-…", "state": "committed" } ] } ❯ stategraph tx logs list --tx 102881bb-… { "results": [ { "action": "state_set", "object_type": "instance", "state_id": "a3f1c0d2-…", "user_id": "f6eca568-…", "created_at": "2026-06-08T19:35:57Z" }, { "action": "hcl_set", "object_type": "resource", "state_id": "a3f1c0d2-…", "user_id": "f6eca568-…", "created_at": "2026-06-08T19:35:57Z" } ] }

every apply · an immutable transaction · attributed to a user, queryable forever

Why the answers hold up

The data is the state

Not a copy

The tables you query are the ones plan and apply write to, so nothing is exported to a CMDB and nothing syncs on a schedule.

Every state at once

One SELECT covers every state and workspace, and JSONB filters reach any resource attribute.

What nobody remembers creating

Gap analysis compares your AWS or GCP account with your states and writes the import blocks and HCL for what no state manages.

See it against your own state

Bring a state file and look at your own resources, dependencies, costs, and change history as one graph you can query.

Book a Demo How SQL inventory works