Skip to content
GitHubXDiscordRSS

Local Development

Learn how to use Alchemy's development mode to run your application locally.

Alchemy’s development mode provides a local development experience for Cloudflare Workers, featuring hot reloading, local resource emulation, and seamless integration with remote Cloudflare services.

To run Alchemy in development mode, use the alchemy dev command to:

  • Emulate Cloudflare Workers and associated resources locally
  • Watch for and auto-apply changes to your infrastructure
  • Hot reload Workers when you make changes to your runtime code
Terminal window
bun alchemy dev

You can also specify additional options:

Terminal window
# run dev mode with default settings
bun alchemy dev
# specify a stage
bun alchemy dev --stage dev
# use a custom script
bun alchemy dev ./my-infra.ts
# use an environment file
bun alchemy dev --env-file .env.dev

In development mode, the Cloudflare Worker resource runs in Miniflare, a local environment that emulates the Cloudflare Workers runtime. By default, Workers run on the first available port beginning at 1337:

const worker = await Worker("my-worker", {
entrypoint: "worker.ts",
});
console.log(worker.url); // http://localhost:1337

You can also set a custom port for the Worker:

const worker = await Worker("my-worker", {
entrypoint: "worker.ts",
dev: {
port: 3000,
},
});
console.log(worker.url); // http://localhost:3000

Route requests from the public internet to your locally running Worker via a Cloudflare Tunnel.

const worker = await Worker("my-worker", {
entrypoint: "worker.ts",
dev: {
tunnel: true,
},
});

Most Cloudflare bindings are automatically emulated in development mode, such as D1Database, KVNamespace, and R2Bucket:

const d1 = await D1Database("my-d1");
const kv = await KVNamespace("my-kv");
const r2 = await R2Bucket("my-r2");
const queue = await Queue("my-queue");
const worker = await Worker("my-worker", {
entrypoint: "worker.ts",
bindings: {
D1: d1,
KV: kv,
R2: r2,
QUEUE: queue,
},
});

Secrets and plain-text bindings are also supported with no additional configuration:

const worker = await Worker("my-worker", {
entrypoint: "worker.ts",
bindings: {
PLAIN_TEXT: "Hello, world!",
API_KEY: alchemy.secret("pk_dev_1234567890"),
},
});

Some Cloudflare resources can be used as bindings in development mode. By default, resources that support local emulation run locally, but you can optionally set dev.remote: true to use the real deployed resource from Cloudflare instead.

const api = await Worker("my-api", {
entrypoint: "api.ts",
dev: {
remote: true, // Use deployed worker instead of local emulation
},
});
const kv = await KVNamespace("my-kv", {
dev: {
remote: true, // Use deployed KV instead of local emulation
},
});
const worker = await Worker("my-worker", {
entrypoint: "worker.ts",
bindings: {
KV: kv,
API: api
},
});
ResourceLocal EmulationRemote BindingDocumentation
Ai❌✅Ai
AnalyticsEngine✅❌AnalyticsEngine
Assets✅❌Assets
BrowserRendering❌✅BrowserRendering
Container✅✅Container
DispatchNamespace❌✅DispatchNamespace
D1Database✅✅D1Database
DurableObjectNamespace❌✅DurableObjectNamespace
Hyperdrive✅❌Hyperdrive
Images✅✅Images
KVNamespace✅✅KVNamespace
Queue✅✅Queue
Pipeline✅❌Pipeline
RateLimit✅❌RateLimit
R2Bucket✅✅R2Bucket
VectorizeIndex❌✅VectorizeIndex
VersionMetadata✅❌VersionMetadata
Worker✅✅Worker
Workflow✅❌Workflow

Alchemy integrates with popular web frameworks, so you can use them with Alchemy’s development mode and access local resources. Typically, you’ll need to update your framework’s configuration with the relevant Alchemy adapter or plugin. For example:

First, use the Astro resource in your alchemy.run.ts script:

alchemy.run.ts
import { Astro } from "alchemy/cloudflare";
const astro = await Astro("my-astro-app");

Then, update your astro.config.mjs file:

astro.config.mjs
import alchemy from "alchemy/cloudflare/astro";
export default defineConfig({
integrations: [alchemy()],
});