The apply-first cycle is a tax you pay every day
Vanilla terraform_remote_state only ever reads the last applied state. A change in a producer module is invisible to its consumers until you apply the producer first — so you're stuck ordering plans and applies by hand.
One plan spans two states
rm1 outputs a port. rm2 reads it and derives firewall rules. We change only rm1 — one plan recomputes both.
# edit rm1 only: http_proxy_port 8080 → 9090, then one plan ❯ stategraph plan State 0 · rm1 (producer) ~ terraform_data.http_proxy_port input: 8080 → 9090 ~ output.http_proxy_port: 8080 → 9090 State 1 · rm2 (consumer: reads rm1's pending output) ~ terraform_data.firewall_rule_port_min input: 8070 → 9080 # http_proxy_port - 10 Plan: 0 to add, 2 to change, 0 to destroy # across 2 states ✓ one plan, one apply. rm2 never waited on apply-rm1-first
rm1: 8080 → 9090 · rm2 firewall ports recompute off the pending value · in the same plan
It's the HCL you already write
No new syntax, no special resources. A normal terraform_remote_state data source is all it takes to adopt cross-state plans — see what's supported →
resource "terraform_data" "http_proxy_port" { input = 8080 } output "http_proxy_port" { value = terraform_data.http_proxy_port.output }
data "terraform_remote_state" "project_a" { backend = "http" config = { address = "https://stategraph/<uuid>" } } resource "terraform_data" "firewall_rule_port_min" { # reads rm1's *pending* output, not last-applied input = data.terraform_remote_state.project_a.outputs.http_proxy_port - 10 }
What you get
Whole blast radius in one plan
Change one module and see every state the change touches — with real diffs — in a single plan. No guessing what's downstream.
Consumers read pending outputs
rm2 sees rm1's planned value, so it's correct before anything is applied. No more "last applied" lag.
One plan, one apply
No apply-A-then-plan-B ordering cycle. The whole change set commits as a single transaction.
New outputs just work
Add a new output attribute and consumers pick it up in the same plan. It's one transaction, not two disjoint states.
Cheaper reads
Stategraph doesn't pull the whole state file to read a couple of outputs — it reads just what you reference.
Zero adoption cost
The same terraform_remote_state HCL you already have is all you need. Point it at a Stategraph state and go.
Stop applying in order
Bring your existing terraform_remote_state wiring. Get cross-state plans, transactional applies, and the entire blast radius in one shot.