---
title: "Alchemy v2"
url: "https://effect-auth.itsbroly.com/infrastructure/alchemy/"
description: "Provision and deploy effect-auth resources on Cloudflare with Alchemy v2."
---



[Alchemy v2](https://alchemy.run) is the primary infrastructure path in the effect-auth examples. The application owns its stack while effect-auth supplies runtime adapters for the resources bound to the Worker.

## Resource ownership [#resource-ownership]

A production Cloudflare auth stack commonly declares:

| Alchemy resource                                 | effect-auth use                                                    |
| ------------------------------------------------ | ------------------------------------------------------------------ |
| `Cloudflare.Worker` or `Cloudflare.Website.Vite` | Runs the Effect HTTP application                                   |
| `Cloudflare.D1.Database`                         | Stores users, credentials, sessions, challenges, and feature state |
| `Cloudflare.DurableObject`                       | Provides globally consistent rate-limit storage                    |
| `Cloudflare.Email.SendEmail`                     | Delivers reset, verification, OTP, approval, and magic-link email  |

Alchemy provisions and binds these resources; it does not choose which auth features or integration level the application uses.

## Minimal stack shape [#minimal-stack-shape]

```ts title="alchemy.run.ts"
import * as Alchemy from "alchemy";
import * as Cloudflare from "alchemy/Cloudflare";
import * as Effect from "effect/Effect";

import type { RATE_LIMITER as RateLimitDurableObject } from "./src/worker";

export const Database = Cloudflare.D1.Database("AuthDatabase", {
  migrationsDir: "./migrations",
});

export const RateLimiter =
  Cloudflare.DurableObject<RateLimitDurableObject>("RATE_LIMITER", {
    className: "RATE_LIMITER",
  });

export const AuthEmail = Cloudflare.Email.SendEmail("AUTH_EMAIL");

export const AuthWorker = Cloudflare.Worker("AuthWorker", {
  main: "./src/worker.ts",
  compatibility: { flags: ["nodejs_compat"] },
  env: {
    DB: Database,
    RATE_LIMITER: RateLimiter,
    AUTH_EMAIL: AuthEmail,
    AUTH_SECRET: process.env.AUTH_SECRET,
  },
});

export default Alchemy.Stack(
  "AppAuth",
  {
    providers: Cloudflare.providers(),
    state: Cloudflare.state(),
  },
  Effect.gen(function* () {
    const worker = yield* AuthWorker;
    return { url: worker.url.as<string>() };
  })
);
```

Use the exact Alchemy version tested by the installed effect-auth release. The current documentation is tested with `alchemy@2.0.0-beta.61`.

## Development and deployment [#development-and-deployment]

```sh
bun alchemy dev
bun alchemy deploy
bun alchemy destroy
```

Generate effect-auth migrations into the directory passed as `migrationsDir` before development or deployment. Keep production secrets in protected deployment environment variables and restrict access to Alchemy state and logs.

See the [Quick Start](/quick-start/) for the complete stack, Worker layers, migrations, environment configuration, browser client, and production caveats.

