1---
2title: Local development
3description: How alchemy dev provides hot reloading, local execution, and local emulation with per-resource opt-in to real cloud services.
4---
5
6import Terminal from "../../../components/Terminal.astro";
7
8`alchemy dev` runs your stack on your machine. Your compute runs
9locally (Workers in workerd, Lambda and ECS in Docker
10containers), the services around it are emulated, and code
11changes hot reload in milliseconds. `Alchemy.remote()` runs any
12resource against the real cloud when you need it.
13
14This page covers the concepts shared by every cloud. For what
15each cloud emulates and how, see the dedicated guides:
16
17- **[Cloudflare local development](/cloudflare/local-development)**
18 — Workers in workerd; simulators for KV, R2, D1, Queues,
19 Hyperdrive, Workflows, Containers, and the Worker binding
20 surface (browser rendering, images, email, cron, Stream, …).
21- **[AWS local development](/aws/local-development)** — Lambda
22 and ECS in Docker containers with close to 40 emulated services
23 (S3, DynamoDB, SQS, SNS, EventBridge, API Gateway, …), no AWS
24 account required.
25
26## How it works
27
28```sh
29alchemy dev
30```
31
32<Terminal content={`[g]✓[/g] [b]Bucket[/b] [d](Cloudflare.R2.Bucket)[/d] [g]created[/g] [d](local)[/d]
33[g]✓[/g] [b]DB[/b] [d](Cloudflare.D1.Database)[/d] [g]created[/g] [d](local)[/d]
34[g]✓[/g] [b]Worker[/b] [d](Cloudflare.Worker)[/d] [g]created[/g] [d](local → workerd)[/d]
35[s2][d]• http://localhost:1337[/d]
36
37[d]Watching for changes ...[/d]`} />
38
39Three things happen:
40
411. **Emulatable services run locally** — resources whose provider
42 ships a local implementation are created as local simulators
43 with `dev:`-prefixed ids. No cloud calls.
442. **Your code runs locally** — Workers execute in workerd,
45 Lambda functions and ECS tasks in Docker containers, websites
46 on their framework's own dev server — with bindings wired to
47 the local simulators.
483. **File changes hot reload** — edit your code and the running
49 compute swaps in the new code without a redeploy.
50
51Resources whose provider has no local implementation deploy to
52the real cloud, into the [`dev_$USER` stage](/environments/stages)
53by default — separate from `alchemy deploy`'s `live_$USER` stage,
54so a bare `alchemy dev` cannot replace a stage you deployed. A
55stack that mixes emulated and live-only resources just works. Tear
56the local-dev stage down with `alchemy destroy --stage dev_$USER`.
57
58## Hot module reloading
59
60<Terminal content={`[d]Watching for changes ...[/d]
61
62[y]↻[/y] [d]src/worker.ts changed[/d]
63[s2][d]• Rebuilding worker ...[/d]
64[g]✓[/g] [b]Worker[/b] [d]reloaded in 42ms[/d]
65
66[y]↻[/y] [d]src/api.ts changed[/d]
67[s2][d]• Rebuilding worker ...[/d]
68[g]✓[/g] [b]Worker[/b] [d]reloaded in 38ms[/d]`} />
69
70- Code changes take effect in **milliseconds**, not minutes
71- Resources stay running across reloads — only your application
72 code is rebuilt
73
74Arbitrary dev processes — Vite, Next, anything with a dev server —
75join the loop via [Command.Dev](/command/dev-servers): started by
76`alchemy dev`, restarted when its inputs change, and a no-op on
77deploy.
78
79## Local by default, live on demand
80
81In dev, emulatable resources are simulators. A local resource's
82id is `dev:`-prefixed, which doubles as proof that no cloud call
83ran.
84
85The local simulators reach beyond your compute's bindings.
86Node-side capability clients follow the same rule: a seed script
87in an [Action](/infrastructure-as-code/action) that writes to a
88`dev:` KV Namespace or S3 bucket lands in the same local
89simulator your Worker or Lambda reads.
90
91Every other resource runs live in dev automatically, and
92`Alchemy.remote()` (below) runs an emulatable resource against
93the real cloud when local fidelity isn't enough.
94
95## Debugging
96
97Because your code runs locally, you can attach a debugger:
98
99- Set breakpoints in your IDE
100- Inspect variables and call stacks
101- Profile performance
102
103## Running a resource live in dev
104
105`Alchemy.remote()` opts a resource out of local emulation — "run
106this live even in dev":
107
108```typescript
109import * as Alchemy from "alchemy";
110
111const worker = yield* Worker("Api", { ... }).pipe(Alchemy.remote());
112```
113
114During `alchemy deploy` the pin is a no-op — everything is live
115anyway. If a remote resource needs credentials you don't have,
116`alchemy dev` tells you before touching anything.
117
118### Opt out a whole scope
119
120```typescript
121yield* Effect.gen(function* () {
122 const api = yield* Worker("Api", { ... });
123 const site = yield* Worker("Site", { ... });
124}).pipe(Alchemy.remote());
125```
126
127The policy is ambient and captured at registration (like
128`adopt()`), so everything inside the scope runs live. Resources
129with no local emulation already run live in dev — `remote()` on
130them is a no-op.
131
132Local and live compose into hybrid topologies — a local Worker
133producing into a live queue whose local consumer drains it, or a
134local Lambda reading a live Secrets Manager secret. See the
135per-cloud guides for examples.
136
137### Switching is a replacement
138
139When a resource moves between local and live — you deploy after a
140dev session, or add/remove `remote()` — it's planned as a
141**replacement**: the new instance is created live, and the local
142one (the workerd instance, the Docker container, the dev process)
143is torn down. Dev state never silently becomes cloud state.
144
145## Dev vs Deploy
146
147| | `alchemy dev` | `alchemy deploy` |
148| ------------------- | ---------------------------------------- | ------------------ |
149| Emulatable services | Local simulators (`remote()` for live) | Deployed to cloud |
150| Everything else | Deployed to cloud (personal stage) | Deployed to cloud |
151| Application code | Runs locally (workerd, Docker) | Deployed to cloud |
152| File watching | Hot reload on change | Manual redeploy |
153| Debugging | Attach local debugger | Tail logs |
154| Speed | Milliseconds | Seconds to minutes |
155
156To automate the deploy side, see the [CI guide](/environments/ci).
157
158## Testing in dev mode
159
160The [test harness](/testing/test-harness) has the same switch:
161`Test.make({ dev: true })` (off by default, on both the Bun and
162Vitest adapters) runs a suite's `deploy(Stack)` against the local
163emulators — Cloudflare in workerd, AWS in Docker — instead of the
164real cloud, so integration tests run on your machine with no cloud
165calls and no separate `alchemy dev` terminal. See
166[Test harness → dev](/testing/test-harness#dev).
167
168## Where next
169
170- [Cloudflare local development](/cloudflare/local-development) — what runs in workerd and which bindings are simulated.
171- [AWS local development](/aws/local-development) — the emulated AWS surface, Lambda/ECS containers, and zero-credential dev.
172- [CI](/environments/ci) — deploy the same stack from GitHub Actions with PR previews.
173- [Stages](/environments/stages) — how `live_$USER`, `dev_$USER`, `pr-42`, and `prod` stay isolated.
174- [Dev servers](/command/dev-servers) — run any framework dev server as a `Command.Dev` resource in the dev loop.
175- [Testing](/testing) — run the same test suite against the local emulators with `Test.make({ dev: true })`.
176- [Local Providers](/infrastructure-as-code/local-provider) — build the local implementation of a resource.