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
AiAi
AnalyticsEngineAnalyticsEngine
AssetsAssets
BrowserRenderingBrowserRendering
ContainerContainer
DispatchNamespaceDispatchNamespace
D1DatabaseD1Database
DurableObjectNamespaceDurableObjectNamespace
HyperdriveHyperdrive
ImagesImages
KVNamespaceKVNamespace
QueueQueue
PipelinePipeline
RateLimitRateLimit
R2BucketR2Bucket
VectorizeIndexVectorizeIndex
VersionMetadataVersionMetadata
WorkerWorker
WorkflowWorkflow

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()],
});