Sharing Data Across States

Scenario: A network team's state exports its entire resource object as one convenient output, and every downstream consumer of that output ends up tightly coupled to the provider's internal schema - while also, as a side effect, gaining visibility into the network team's whole state snapshot.

Separate states (across teams, environments, or services) sometimes genuinely need to share a narrow integration fact with each other - most commonly something like "what's the ID of the shared network I should attach to." The built-in terraform_remote_state data source reads another state's outputs directly, which sounds narrow and safe, but the important caveat is that in practice it commonly requires - and grants - read access to that state's entire snapshot, not just the specific output you meant to read. If that upstream state contains anything sensitive, terraform_remote_state access is effectively a much bigger permission grant than "share one integration value" implies.

HCP Terraform's tfe_outputs data source is a narrower alternative purpose-built for exposing just outputs, with tighter intended scope than a full state read. Other common patterns sidestep state-sharing entirely: publishing a value to a dedicated parameter store, a DNS record, or a provider-native data source that the consuming state queries independently. Whatever mechanism you choose, be deliberate about direction: design your states as a one-way dependency graph (network → services → applications, say) and actively avoid cycles, where state A depends on an output from state B while B also depends on an output from A - that's structurally undecidable, similar to the acyclic-graph requirement you learned about back in Module 1.

Analogy: Independent Terraform states are like separate bounded departments in a company. A healthy cross-department relationship shares a documented, narrow public API - a specific report, a specific approved data feed - not a standing copy of the neighboring department's entire private database, which is effectively what a broad terraform_remote_state read grants if you're not careful about what that upstream state actually contains.

A worked configuration

data "terraform_remote_state" "network" {
  backend = "remote"
  config  = { workspace = "network-prod" }
}
locals { network_id = data.terraform_remote_state.network.outputs.network_id }

Minimize what any given state exposes through outputs in the first place, and think about classification the same way you did with sensitive outputs in Module 4 - if an upstream state's outputs are ever going to be readable by a totally different team's Terraform run, treat everything in that state as something that team could potentially see. Run triggers (queuing a downstream run when an upstream one completes) can help sequence work across states, but they don't remove the underlying architectural coupling - any change to a shared value still needs coordination and, often, a compatibility window while consumers catch up.

Common mistakes in production

Goal: Treat the plan as a change contract: understand every create, update, replacement, and destroy before approving it. Reinforce this lesson in the tf-cross-state-outputs Terraform lab. Open /labs/terraform and choose slug tf-cross-state-outputs; the lab runs real Terraform against the offline FakeCloud provider.