Pulumi Stack References: Architecture Note for Safe Cross‑Stack Data Sharing
Learn the requirements, minimal design, trust boundaries, operational checks, failure modes, and change triggers for Pulumi Stack References to safely share data between stacks.
20 Mar 2026, 16:46 UTC

Requirements
To use a Pulumi Stack Reference, the producer and consumer stacks must reside in the same Pulumi backend—either the Pulumi Service or a self‑managed backend—and they must share a compatible state version. The producer stack needs at least one successful update so that its outputs are present in the state; otherwise the reference will fail to resolve.
Minimal Suitable Design
The smallest functional design consists of two stacks in the same project:
- Producer stack – declares the resources you want to share (e.g., a VPC) and exports the needed values using
pulumi exportor by returning them from the stack’sindex.ts. - Consumer stack – creates a
new pulumi.StackReference("//")and retrieves each exported value withstackRef.getOutput(""). No additional Pulumi resources are required just for the reference itself.
Example (TypeScript)
// producer stack: infra/producer/index.ts
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const vpc = new aws.ec2.Vpc("shared-vpc", {
cidrBlock: "10.0.0.0/16",
tags: { Environment: "shared" }
});
export const vpcId = vpc.id;
// consumer stack: app/consumer/index.ts
import * as pulumi from "@pulumi/pulumi";
const producerRef = new pulumi.StackReference("myorg/myapp/producer");
const vpcId = producerRef.getOutput("vpcId");
// Use the exported ID, e.g., to create subnets
const subnet = new aws.ec2.Subnet("app-subnet", {
vpcId: vpcId,
cidrBlock: "10.0.1.0/24",
tags: { Environment: "app" }
});
// Optionally expose the subnet ID for further stacks
export const subnetId = subnet.id;
Trust and Data Boundaries
The consumer stack receives only the values that the producer explicitly exports. It cannot invoke any of the producer’s resources or modify its state. If a value is sensitive (e.g., a database password), the producer must mark it as a secret when exporting:
export const dbPassword = pulumi.secret("my‑secret‑password");When marked as secret, Pulumi encrypts the value in transit and at rest, and it will not appear in plain‑text logs or the consumer’s state file.
Operational Checks
- List references: Run
pulumi stack referencein the consumer stack to see which producer stacks are referenced and their current resolved values. - Verify freshness: After updating the producer, run
pulumi refresh(orpulumi upwith--refresh) on the consumer. The refreshed values should match the producer’s latest outputs. - Drift detection: Compare the consumer’s resolved outputs with the producer’s current outputs using
pulumi stack outputon each stack. Any divergence indicates that the consumer has not been refreshed after a producer change. - Permissions: The user running the commands must have read access to the producer stack’s state in the backend. No write permission is needed for the reference itself.
- Risk: If the producer stack is deleted or its state is corrupted, the consumer will fail to resolve the reference during the next update.
Failure Modes and Design Change Triggers
Circular References
If Stack A references Stack B and Stack B references Stack A, Pulumi detects the cycle at update time and stalls both stacks with an error similar to "circular stack reference detected". To avoid this, model dependencies as a directed acyclic graph (DAG).
Renaming or Removing Exported Keys
Changing the name of an exported output or deleting it breaks any consumer that calls getOutput for that key, resulting in a "missing output" error during the consumer’s update. The fix is to update all consumers to use the new key or to add a compatibility shim in the producer.
Renaming the Producer Stack, Project, or Organization
The Stack Reference string encodes <org>/<project>/<stack>. Any change to these components requires updating the reference in every consumer stack. Failing to do so causes an "unable to find stack" error.
Backend Migration
Moving stacks from a self‑managed backend to the Pulumi Service (or vice‑versa) changes the endpoint where state is stored. After migration, you must re‑configure the Stack Reference to point to the new backend URL (if using a self‑managed backend) or update the organization/project names. State migration tools should be used to preserve history; otherwise, consumers will see the producer as having no updates.
Conditions That Would Change the Design
- If you need to share large binary objects (e.g., container images), consider exporting a reference to an external artifact registry instead of the raw binary via Stack References.
- When fine‑grained access control is required—different teams should see only subsets of exported values—split the producer into multiple stacks, each exporting a specific subset, and reference only the needed stacks.
- If the consumer must react to changes in real time (e.g., trigger a CI pipeline), supplement Stack References with an event‑driven mechanism such as a webhook or a Pulumi Automation API watcher.
Practical Verification Steps
- Create two stacks in the same project:
prod-infra(exportingvpcId) andapp(referencingprod-infra). - Run
pulumi uponprod-infrafirst; confirm the update succeeds and thevpcIdoutput appears. - Run
pulumi uponapp; verify that the consumer’s logs show the resolved VPC ID and that any resources using it are created. - Modify the producer (e.g., add a tag to the VPC), run
pulumi uponprod-infra. - Run
pulumi refreshonapp(orpulumi upwith--refresh) and check that the updated tag propagates without changing the consumer code. - Introduce a deliberate circular reference (app referencing prod-infra and prod-infra referencing app) and run
pulumi upon either stack; observe the error message confirming detection.
These steps let you confirm that the reference works, that updates flow correctly, and that failure modes are surfaced as expected. No state‑changing rollback is required for the reference itself; if a consumer update fails due to a broken reference, simply fix the reference string or restore the producer’s exported output and re‑run the update.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.