Simplify Multi‑Stack Deployments with Pulumi Stack References
Learn how Pulumi’s stack references let you share infrastructure outputs—like a VPC ID—across separate stacks, reduce duplication, and keep teams in sync. A practical example, trade‑offs, and step‑by‑step guide.
22 Apr 2026, 10:17 UTC

Problem: Duplicated Infrastructure Across Stacks
In many teams, a single Pulumi project is split into multiple stacks—for example, a network stack that provisions a VPC and an app stack that deploys micro‑services inside that VPC. Without a clean way to share outputs, each stack ends up recreating the same resources or hard‑coding IDs. This leads to:
- Repetitive code and configuration
- Inconsistent state when the VPC changes
- Hard‑to‑maintain cross‑stack dependencies that are discovered only at runtime
Thesis: Centralize Shared Infrastructure with Stack References
Pulumi’s stack reference lets one stack expose outputs that another stack can consume. By placing shared resources in a dedicated stack (e.g., network), you:
- Keep code DRY and maintainable
- Enforce a single source of truth for shared IDs
- Make ownership and change management explicit
Concrete Example: Sharing a VPC ID
Below is a minimal, language‑agnostic illustration using TypeScript. The same concepts apply to Python, Go, or C#.
1. Create the Network Stack
import * as pulumi from "pulumi";
import * as aws from "@pulumi/aws";
const vpc = new aws.ec2.Vpc("appVpc", {
cidrBlock: "10.0.0.0/16",
});
// Export the VPC ID so other stacks can reference it
export const vpcId = vpc.id;
2. Deploy the Network Stack
# From the network stack directory
pulumi stack init dev
pulumi up
After the stack finishes, the output vpcId is stored in the Pulumi backend.
3. Create the App Stack
import * as pulumi from "pulumi";
import * as aws from "@pulumi/aws";
// Reference the network stack – replace / with your values
const network = new pulumi.StackReference("org/project/network");
// Pull the exported VPC ID
const vpcId = network.getOutput("vpcId");
// Use the VPC ID in the app resources
const ec2 = new aws.ec2.Instance("appServer", {
ami: "ami-0c55b159cbfafe1f0", // example AMI
instanceType: "t2.micro",
subnetId: vpcId, // this is a simplified example; normally you’d reference a subnet
});
4. Deploy the App Stack
# From the app stack directory
pulumi stack init dev
pulumi up
During pulumi up, Pulumi automatically fetches the vpcId from the network stack and uses it when provisioning the EC2 instance.
Trade‑Offs and Limitations
- Tighter Coupling – The app stack depends on the network stack. A change that alters the exported output (e.g., switching to a different VPC ID) will trigger a redeploy of the app stack.
- Backend Compatibility – Stack references only work when both stacks share the same backend (e.g., Pulumi Service, local file, or S3). A reference to a stack in a different backend will fail.
- Secret Exposure – If a stack outputs a secret, the consuming stack must be able to decrypt it. Ensure encryption is enabled and that the backend supports secret storage.
- Versioning – Pulumi does not automatically pin the referenced stack to a specific revision. It always pulls the latest state. To avoid accidental breaking changes, document the expected output shape and consider adding a version label to the stack’s outputs.
Practical Checklist for a Smooth Implementation
- Define a dedicated shared stack (e.g.,
network) and list all outputs you want to expose. - Export outputs with clear names and document their purpose in the stack’s README.
- Secure secrets – Mark outputs as
pulumi.secretif they contain sensitive data. - Pin to a stack revision – Use
network.getOutput("vpcId", {version: "v1.2.3"})if you need to lock to a specific output version. - Test cross‑stack changes – Modify an output in the source stack, run
pulumi up, then runpulumi upin the consuming stack to verify that only the necessary resources are redeployed. - Automate with CI – Add a pipeline step that runs
pulumi previewfor each stack and fails if the preview shows unexpected changes.
Conclusion
Stack references give teams a clean, declarative way to share infrastructure outputs across Pulumi stacks. By centralizing shared resources, you reduce duplication, enforce consistent configuration, and make ownership explicit. Just remember that changes in the source stack ripple through all consumers, so adopt version pinning and clear change‑management practices to keep deployments predictable.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.