Skip to content

Stacks

A Stack is the top-level unit of deployment in Alchemy. It groups resources together, wires up providers, and tracks state across deploys.

A Stack is just an Effect that you export default from a TypeScript file:

import * as Alchemy from "alchemy";
import * as Cloudflare from "alchemy/Cloudflare";
import * as Effect from "effect/Effect";
export default Alchemy.Stack(
"MyApp",
{ providers: Cloudflare.providers(), state: Cloudflare.state() },
Effect.gen(function* () {
const bucket = yield* Cloudflare.R2.Bucket("Bucket");
return { bucketName: bucket.bucketName };
}),
);

Alchemy.Stack takes three arguments:

  1. Name — identifies this stack in state storage
  2. Optionsproviders and state, both required (see State Store for the available state layers)
  3. Effect — a generator that declares resources and returns outputs

The value returned from the generator becomes the stack output. After a deploy, outputs are printed to the console and available programmatically in tests.

Effect.gen(function* () {
const bucket = yield* Cloudflare.R2.Bucket("Bucket");
const worker = yield* Worker;
return {
bucketName: bucket.bucketName,
url: worker.url,
};
});

The CLI renders them after every successful deploy:

alchemy · dev_samDEPLOY
$

Every deploy targets a stage — an isolated instance of the stack like dev_sam, staging, or prod. The stage defaults to dev_$USER, so each developer gets their own environment automatically. State and physical names are namespaced by stage.

Terminal window
# Each stage = its own state file + its own physical names.
$ alchemy deploy --stage dev_sam # -> myapp-dev_sam-photos-a3f1
$ alchemy deploy --stage pr-147 # -> myapp-pr_147-photos-9b2c
$ alchemy deploy --stage prod # -> myapp-prod-photos-7d4e
# Three independent deployments. Destroying one
# never touches the others.

For naming patterns, isolation, and per-stage configuration see Stages. Credentials per environment are managed via Profiles.

Inside a resource or layer, you can access the current Stack’s metadata via the Stack service:

import { Stack } from "alchemy/Stack";
import * as Console from "effect/Console";
Effect.gen(function* () {
const stack = yield* Stack;
yield* Console.log(stack.name); // "MyApp"
yield* Console.log(stack.stage); // "dev_sam"
const queue = yield* SQS.Queue("Jobs").pipe(
RemovalPolicy.retain(stack.stage === "prod"),
);
});

When you declare a resource at module scope (outside any Effect.gen), there is no yield* available to read the Stack service. But a Resource’s props can themselves be an Effect — Stack.useSync builds one that computes props from the current stack, useful for parameterizing names by stage:

import * as Axiom from "alchemy/Axiom";
import { Stack } from "alchemy/Stack";
export const Traces = Axiom.Dataset(
"Traces",
Stack.useSync(({ stage }) => ({
name: `${stage}-traces`,
kind: "otel:traces:v1" as const,
description: `OTEL traces for stage '${stage}'`,
retentionDays: 30,
})),
);

The function runs once at plan time, after the stage is resolved. Use it anywhere a resource accepts a props object.

A typed Alchemy.Stack handle lets one stack read another’s persisted outputs at plan time:

// backend/src/Stack.ts — typed handle shared across packages
export class Backend extends Alchemy.Stack<
Backend,
{ url: string }
>()("Backend") {}
// frontend/alchemy.run.ts — reads the matching stage of Backend
import { Backend } from "backend";
export default Alchemy.Stack(
"Frontend",
{
providers: Cloudflare.providers(),
state: Cloudflare.state(),
},
Effect.gen(function* () {
const backend = yield* Backend;
const website = yield* Cloudflare.Website.Vite("Website", {
env: { VITE_API_URL: backend.url },
});
return { url: website.url.as<string>() };
}),
);

yield* Backend defaults to the current stagesam frontend reads sam backend, pr-42 reads pr-42. Use Backend.stage.<name> to pin to a specific stage instead.

See References for the underlying operators and Monorepo for the end-to-end walkthrough (package layout, schema sharing, deploy ordering).

A stack is just the container — the things it deploys are Resources.

  • Resources — the named entities a stack deploys.
  • Stages — naming, isolation, per-stage configuration.
  • Monorepo — one stack or many across packages.