References
A reference reads something already deployed — a different stage, a different Stack, or both — from the persisted state store at plan time. References are lazy and don’t drift: every plan re-reads the upstream’s state, so downstream always sees whatever was actually last deployed.
Reference another stage
Section titled “Reference another stage”Resource.ref takes a Logical ID; pass stage to read that
Resource from a different stage of this stack:
const { stage } = yield* Alchemy.Stack;
const project = stage.startsWith("pr-") ? yield* Neon.Project.ref("app-db", { stage: "staging" }) : yield* Neon.Project("app-db", { region: "aws-us-east-1" });The ref has the same type as yield* Neon.Project("app-db", { … })
— pass it anywhere the real thing is accepted. Here staging owns
the database and pr-* stages borrow it; destroying a borrower
never touches the Resources it references.
Reference another Stack
Section titled “Reference another Stack”Pass stack too for a Resource in a different Stack:
const sharedBucket = yield* Storage.Bucket.ref("Assets", { stack: "shared-infra", stage: "prod",});{ stack, stage, id } is the full address; anything you omit
defaults to the current stack/stage. Pin stage when the stacks’
stages don’t line up — pr-147 has no counterpart in
shared-infra.
Depend on a Stack’s outputs
Section titled “Depend on a Stack’s outputs”When the unit you consume is a whole Stack, import its tag and yield it:
export class Backend extends Alchemy.Stack< Backend, { url: string }>()("Backend") {}// inside the frontend Stack's Effect.genconst a = yield* Backend; // current stageconst b = yield* Backend.stage.prod; // pinned to "prod"const c = yield* Backend.stage["pr-42"]; // any stage nameEvery successful apply persists what the Stack’s effect returned
as a per-stage output record; yield* Backend reads it back as a
proxy of typed Outputs, so (yield* Backend).url is
Output<string>. Full two-package walkthrough:
Multiple Stacks.
Escape hatches
Section titled “Escape hatches”When the Resource constructor isn’t in scope, Output.ref is the
same lookup:
const bucket = Output.ref<typeof Bucket>("Bucket", { stack: "shared-infra", stage: "prod",});When a typed Stack handle isn’t in scope, Output.stackRef reads
the output record directly:
const backend = yield* Output.stackRef<{ url: string }>("Backend", { stage: "prod",});Prefer Resource.ref and yield* MyStack — same lookups, real
type bindings.
Deploy order
Section titled “Deploy order”The upstream must already be deployed to the exact
{ stack, stage } the reference names, or the plan fails fast
with a typed InvalidReferenceError — there is no
deploy-and-hope path:
alchemy deploy --stage staging # creates app-dbalchemy deploy --stage pr-147 # borrows staging's app-dbDestroy in reverse order. Resolution itself is the in-stack Output flow with one difference: a reference’s upstream was reconciled by a previous deploy, so only its persisted attributes participate in this plan.
Where next
Section titled “Where next”- Multiple Stacks — typed Stack handles wiring a monorepo.
- Shared database across stages — the owner/borrower pattern end to end.
- Inputs & Outputs — the Output model references plug into.
- State Store — where the persisted state that refs read lives.