Alchemy is an Infrastructure-as-Effects framework. It extends
Infrastructure-as-Code by combining your cloud resources and the
application logic that uses them into a single, type-safe program
powered by Effect.
Infrastructure-as-Code vs Infrastructure-as-Effects
Traditional IaC tools like Terraform, Pulumi, and CDK separate
infrastructure definitions from application code. You write your
infrastructure in one place and your business logic in another, then
wire them together with environment variables, ARNs, and config
files.
Alchemy takes a different approach: infrastructure and logic are
Effects in the same program.
// alchemy.run.ts — infrastructure and logic in one program
import*as Alchemy from"alchemy";
import*as Cloudflare from"alchemy/Cloudflare";
import*as Effect from"effect/Effect";
import Worker from"./src/worker.ts";
constBucket= Cloudflare.R2Bucket("Bucket");
exportdefaultAlchemy.Stack(
"MyApp",
{ providers: Cloudflare.providers() },
Effect.gen(function* () {
constbucket=yield* Bucket;
constworker=yield* Worker;
return { url: worker.url };
}),
);
// src/worker.ts — the Worker binds the Bucket directly
The Bucket resource, the Worker resource, and the runtime fetch
handler all live in the same codebase, composed with the same
yield* syntax. There’s no separate “infra” project — it’s one
program.
Alchemy uses TypeScript and Effect’s type system to catch mistakes at
compile time. If you forget to provide the right providers for your
resources, the compiler tells you:
This layer provides no services and can be used as a neutral element
in layer composition or as a starting point for building layers.
@example
import { Layer } from"effect"
constemptyLayer= Layer.empty
@since ― 2.0.0
@category ― constructors
empty,
Error ts(2322) ― Type 'Layer<never, never, never>' is not assignable to type 'Layer<NoInfer<Providers>, never, StackServices>'.
Type 'ProviderCollectionShape<"Cloudflare">' is not assignable to type 'never'.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
gen allows you to write code that looks and behaves like synchronous
code, but it can handle asynchronous tasks, errors, and complex control flow
(like loops and conditions). It helps make asynchronous code more readable
and easier to manage.
The generator functions work similarly to async/await but with more
explicit control over the execution of effects. You can yield* values from
effects and return the final result at the end.
A Resource is any cloud entity managed by Alchemy — buckets,
databases, queues, workers, IAM roles, DNS records, and more. Each
resource is declared as an Effect and yield*-ed inside a Stack:
constbucket=yield* Cloudflare.R2Bucket("Bucket");
constdb=yield* Cloudflare.D1Database("DB");
constqueue=yield*AWS.SQS.Queue("Jobs");
Resources are just descriptions until they’re yielded. You can
declare them in separate files and import them from anywhere: