# Alchemy treats cloud resources as Effect values in one TypeScript program

> Alchemy is a TypeScript infrastructure framework that writes infrastructure and application logic as a single Effect program, so a bucket and the worker that reads it live in the same file. Version 2 is still beta and the project warns that breaking changes are expected.

**alchemy-run/alchemy** — Infrastructure as Effects

- Repository: https://github.com/alchemy-run/alchemy
- Website: https://alchemy.run
- Stars: 1,727 · Forks: 251
- Language: TypeScript
- License: Apache-2.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/alchemy-run-alchemy

## One program instead of a stack file and an application

Most infrastructure tooling asks you to describe resources in a separate file, in a different language, and then to read the values those resources produce back into your application code by hand. Alchemy takes the opposite position. It describes the cloud infrastructure and the application logic as a single type-safe Effect program, with resources, functions, IAM and SDK calls all in the same Effect program and no YAML and no second runtime. The claim in the project documentation is that everything is one program in one language, and the practical consequence is that the values flowing between the infrastructure layer and the application layer are ordinary typed values rather than strings you re-declare. The audience is TypeScript developers who have already chosen Effect as their runtime model and want infrastructure declarations to live under the same compiler and the same type checker as the rest of the codebase.

## A bucket and the worker that serves it in the same file

The README opens with a Cloudflare example that shows the whole idea in one place. The resource is declared as a value, and the worker is declared as another value that consumes it:

```typescript
import * as Cloudflare from "alchemy/Cloudflare";
import * as Effect from "effect/Effect";
import * as HttpServerResponse from "effect/http/HttpServerResponse";

export const Uploads = Cloudflare.R2.Bucket("Uploads");
```

The worker is built by calling Cloudflare.Worker with a name, a main module, and an Effect program that yields the bucket:

```typescript
const bucket = yield* Cloudflare.R2.ReadWriteBucket(Uploads);
```

From there the bucket behaves like any other typed handle, and the read path is ordinary Effect code with no string lookups of environment variables:

```typescript
const obj = yield* bucket.get("hello.txt");
return obj
  ? HttpServerResponse.text(yield* obj.text())
  : HttpServerResponse.text("Not found", { status: 404 });
```

That is the design in miniature: the binding that Cloudflare needs at deploy time and the client that the handler uses at runtime come from the same declaration.

## ReadWriteBucket replaces the binding line, the policy and the env lookup

The single most repeated claim in the project documentation is about bindings rather than glue code. The example given is AWS.S3.GetObject(bucket), which the documentation says wires the IAM policy, the environment variable and a typed SDK call in a single line. On the Cloudflare side, the same idea appears as the ReadWriteBucket call in the opening example: one call adds the Worker binding at deploy time and hands back a typed client at runtime. Another stated property is that cloud API failures arrive as tagged Effect errors, so a failure is part of the type system and is either handled or deliberately ignored. This is where the framework differs in kind from a declarative provisioning tool. A file-based generator produces a plan and then stops; here the plan and the application that runs against the provisioned resources are values in the same program, and the compiler is what connects them.

## Adding the packages and driving the CLI

The documented install step is a single pnpm command that pulls the framework, the Effect runtime and both platform packages:

```bash
pnpm add alchemy@latest effect @effect/platform-bun @effect/platform-node
```

The CLI is invoked as alchemy, and the repository's own scripts show the shape of the commands. Deployment runs against a stack file:

```bash
alchemy deploy ./stacks/github.ts --profile admin
```

and state can be cleared with a command whose own name is a warning:

```bash
alchemy state unsafe nuke --config ./stacks/nuke.ts
```

The name of that second command is worth taking literally. The same program is used across local development, plan, deploy, smoke tests and CI, which is the argument for the single-model approach, but it also means the file that describes your infrastructure is the same artifact that gets applied and destroyed. There is no separate staging environment described in the documentation for a given stack, so separation between environments has to be expressed inside the stack files themselves.

## The GitHub Action expects the CLI to already exist

Alchemy ships a root GitHub Action, and the workflow snippet in the documentation is short. The action deploys prod from main, deploys pull request previews as staging-{number}, and destroys the pull request previews when the pull request closes:

```yaml
- uses: alchemy-run/alchemy@main
  env:
    CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
    CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

One condition is stated plainly: the workflow must install the alchemy CLI before this action runs. The action therefore does not bootstrap the tool, it drives a tool that is already present in the runner. Note also that the action is referenced at the main branch rather than at a version tag, so what runs in your pipeline is whatever the main branch contains at the moment of the run. The documentation does not describe pinning this action to a commit, and that is a decision your team has to make rather than one the project makes for you.

## A documentation index written for coding agents

The project takes agent-assisted development seriously enough to ship a bootstrap prompt. The documentation says to paste it into Claude Code, Cursor, or any agent that can fetch a URL. It instructs the agent to read https://alchemy.run/llms.txt to load the full documentation index, then act as a pair on the project, following patterns from the docs and the examples folder, staying idiomatic to Effect by using Layers for wiring and returning Effects from lifecycle code, and asking before introducing new dependencies or breaking conventions. The repository layout backs this up with agent-facing directories such as .agents/, .claude/, AGENTS.md and CLAUDE.md, alongside a stacks/ directory and an examples/ directory that contains runnable AWS and Cloudflare projects. The effect-oriented conventions in the prompt are the same ones an experienced Effect user would follow, which means an agent that has not written Effect before will need the examples folder more than the prompt.

## v2 is beta, and the release history shows why that label matters

The maintenance picture is good in the short term and unsettled in the long term. The last push was on 2026-10-19, and the release list shows three beta builds in October 2026, with v2.0.0-beta.83 and v2.0.0-beta.82 published on the same day, 2026-10-12, and v2.0.0-beta.81 on 2026-10-05. Two beta tags landing on the same calendar day is the clearest signal that the API surface is still moving. The README states plainly that v2 is in beta and that breaking changes are expected, and it points readers to the Discord rather than to a migration guide. The licence is Apache 2.0, with code incorporated from upstream projects collected in a third-party licences file, so a fork or an embed carries obligations beyond the repository's own licence. The project is young enough that the cost of an upgrade is best estimated by the number of provider calls in your stack files, not by the version number in package.json.

## Where the Effect dependency stops being an advantage

There are two clear failure modes. The first is organisational: a team that has not adopted Effect inherits the framework's learning curve before it inherits its benefits, and the deployment plan is not a piece of YAML a platform engineer can read without knowing how Effect programs are structured. The second is that the beta contract moves under you, and the documentation for a stack is code, so an upstream change surfaces as a type error or a behavioural difference rather than as a diff in a template file. A reasonable alternative for many teams is to keep infrastructure in the provider's own native tooling and keep the application in TypeScript, accepting that the binding identifiers cross the boundary as strings. The difference in approach is precise: Alchemy makes the boundary type-checked inside one program, at the cost of a runtime model and framework version you have to upgrade alongside your application.

## Conclusion

Alchemy makes sense for teams that already write Effect and want the resource graph, the deployment plan and the runtime handler in one TypeScript program, and it is a poor fit for anyone who needs a stable 1.x contract, since v2 is in beta and the project states that breaking changes are expected. Before adopting it, read the plan output of your own stack file rather than trusting the type checker, pin the exact beta version you tested because the most recent releases moved within a single day, and confirm that the providers you need are covered by the alchemy packages you intend to depend on.

## FAQ

### Is Alchemy stable enough for production use?

The project states that v2 is in beta and that breaking changes are expected. The most recent listed releases are v2.0.0-beta.83 and v2.0.0-beta.82, both published on 2026-10-12, and the last push was on 2026-10-19.

### Which cloud providers does Alchemy support?

The documentation lists AWS, Cloudflare, GCP, Fly, Hetzner, Kubernetes, Railway, Neon, PlanetScale and Stripe among the providers covered by the same model. The examples folder in the repository contains runnable projects for AWS and Cloudflare.

### How do I deploy an Alchemy stack from a GitHub Actions workflow?

Use the root action, which deploys prod from main and pull request previews as staging-{number}. The documentation states that the workflow must install the alchemy CLI before the action runs.

### What licence is Alchemy released under?

The project is licensed under the Apache License 2.0. Code incorporated from upstream projects is listed separately in the third-party licences file in the repository.

## Sources

- [alchemy-run/alchemy on GitHub](https://github.com/alchemy-run/alchemy)
- [License: Apache-2.0](https://github.com/alchemy-run/alchemy/blob/main/LICENSE)
- [Project website](https://alchemy.run)
- [README](https://github.com/alchemy-run/alchemy/blob/main/README.md)
- [Releases](https://github.com/alchemy-run/alchemy/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/alchemy-run-alchemy
