1---
2title: Local development
3description: alchemy dev runs your AWS stack on your machine — Lambda in Docker containers, local S3/DynamoDB/SQS, event sources firing, hot reload — with no AWS account or credentials required.
4---
5
6import Terminal from "../../../components/Terminal.astro";
7
8`alchemy dev` runs your AWS stack entirely on your machine — no
9AWS account, no credentials, no config. Lambda functions execute
10in Docker containers behind working Function URLs, websites run
11their frameworks' own dev servers with native HMR, ECS tasks run
12as real containers, and the surrounding services (S3, DynamoDB,
13SQS, SNS, EventBridge, and many more) are emulated locally. Code
14changes hot reload in ~100–500ms.
15
16```sh
17alchemy dev
18# no AWS credentials — using the local emulator
19```
20
21<Terminal content={`[g]✓[/g] [b]Files[/b] [d](AWS.S3.Bucket)[/d] [g]created[/g] [d](local)[/d]
22[g]✓[/g] [b]Users[/b] [d](AWS.DynamoDB.Table)[/d] [g]created[/g] [d](local)[/d]
23[g]✓[/g] [b]Jobs[/b] [d](AWS.SQS.Queue)[/d] [g]created[/g] [d](local)[/d]
24[g]✓[/g] [b]Api[/b] [d](AWS.Lambda.Function)[/d] [g]created[/g] [d](local → docker)[/d]
25[s2][d]• http://b71ff5c0….lambda-url.us-east-1.localhost:4566/[/d]
26
27[d]Watching for changes ...[/d]`} />
28
29## How it works
30
31Local AWS emulation is powered by
32[our fork](https://github.com/alchemy-run/floci) of
33[floci](https://floci.io), an MIT-licensed LocalStack-style
34emulator. The emulator starts automatically in Docker — one
35container (`alchemy-floci`) shared across projects and sessions —
36and your stack deploys into it in seconds. Resource identifiers
37carry the `dev:` marker and local endpoints
38(`localhost:4566`), which doubles as proof that no cloud call
39ran.
40
41We hold the emulator to the same bar as the real cloud: alchemy's
42live AWS test suites — the control-plane lifecycle tests and the
43data-plane binding tests that normally run against real AWS —
44also run against the emulator, and every fidelity gap they
45surface becomes a fix in the fork.
46
47## Lambda runs in containers
48
49Each Lambda function executes in a local runtime container behind
50a working Function URL:
51
52```typescript
53export default class Api extends AWS.Lambda.Function<Api>()(
54 "Api",
55 { main: import.meta.url, functionUrl: true },
56 Effect.gen(function* () {
57 const files = yield* AWS.S3.Bucket("Files");
58 const jobs = yield* AWS.SQS.Queue("Jobs");
59
60 const putObject = yield* AWS.S3.PutObject(files);
61 const sendMessage = yield* AWS.SQS.SendMessage(jobs);
62
63 return {
64 fetch: Effect.gen(function* () {
65 yield* putObject({ Key: "hello.txt", Body: "hello" });
66 yield* sendMessage({ MessageBody: "process hello.txt" });
67 return yield* HttpServerResponse.text("ok");
68 }).pipe(Effect.orDie),
69 };
70 }).pipe(
71 Effect.provide([AWS.S3.PutObjectHttp, AWS.SQS.SendMessageHttp]),
72 ),
73) {}
74```
75
76In dev, the function serves at a working local Function URL
77(`http://….lambda-url.us-east-1.localhost:4566/`), `putObject`
78lands in the local bucket, and `sendMessage` lands in the local
79queue. The SDK honors the standard `AWS_ENDPOINT_URL` environment
80override that the emulator injects into every dev container.
81
82Save the file and the running function serves the new code in
83**~100–500ms** — no redeploy, no restart. The dev session watches
84your code's module graph, rebuilds, and swaps the code under the
85live Function URL.
86
87## Websites run their own dev servers
88
89Every `AWS.Website.*` resource — Vite, Next.js, Astro, Nuxt,
90SvelteKit, Waku, Octane, StaticSite — runs its framework's own
91dev server under `alchemy dev`: native HMR, no cloud resources.
92The site's `url` is the local dev server's address:
93
94```typescript
95const site = yield* AWS.Website.Vite("Web");
96// dev: site.url = http://localhost:5173 — Vite's own dev server, HMR included
97// deploy: site.url = the CloudFront distribution
98```
99
100The same stack deploys unchanged: `alchemy deploy` runs
101`vite build` and serves the output from S3 through CloudFront. For
102SSR frameworks, `server.environment` is delivered to the dev
103server's process env, so config reads work the same locally and
104deployed. See [AWS frontends](/aws/frontend/websites).
105
106## ECS tasks run as containers
107
108ECS tasks and services run as real Docker containers, built and
109pushed through a local OCI registry:
110
111```typescript
112// bundled Effect program — built into an image, pushed through
113// a local registry, running as a real container seconds later
114export default class Web extends AWS.ECS.Task<Web>()(
115 "Web",
116 { main: import.meta.url, port: 8080 },
117 Effect.gen(function* () {
118 return {
119 fetch: Effect.gen(function* () {
120 return HttpServerResponse.text("hello from a local container");
121 }),
122 };
123 }),
124) {}
125```
126
127Bring-your-own-Dockerfile containers work too:
128`AWS.ECS.Service("Api", { context: "./api", port: 3000 })` builds
129your image and runs it the same way.
130
131The whole live pipeline runs unchanged: image build, `docker
132push`, task definitions, `RunTask`, and services that converge
133exactly like AWS. Hot reload swaps a running container in ~6
134seconds — bundled tasks watch the deploy's exact module graph,
135Dockerfile tasks watch the build context, and services roll their
136tasks onto the new image revision. Emulated ALB listeners route
137to the local containers; each task is also reachable directly at
138its literal host port (`localhost:<port>`).
139
140## Event sources fire locally
141
142The glue between services works end to end in the emulator:
143SQS→Lambda event source mappings poll and deliver batches, S3
144notifications fire, EventBridge rules route, SNS subscriptions
145deliver, DynamoDB Streams pump changes, and EventBridge Scheduler
146schedules fire — so a `consumeQueueMessages` handler in a local
147Lambda drains a local queue exactly like it would in the cloud.
148
149## What's emulated
150
151Close to 40 services and over 200 resource types run against the
152local emulator in dev:
153
154| Category | Services |
155| ------------------- | ------------------------------------------------------------------------------------------------------------------- |
156| Compute | Lambda (functions, layers, versions, aliases, event source mappings, permissions), ECS, ECR, Batch, Auto Scaling, Application Auto Scaling |
157| APIs & delivery | API Gateway (REST), API Gateway v2 (HTTP & WebSocket), AppSync, CloudFront (Distributions, Functions, KeyValueStore), WAFv2, ACM |
158| Storage & databases | S3, DynamoDB, RDS, Glue, Athena, S3 Vectors |
159| Messaging & events | SQS, SNS, EventBridge, Kinesis, Firehose, Pipes, Scheduler, Step Functions |
160| Networking & DNS | EC2 (VPCs, subnets, security groups, instances, …), ELBv2, Route 53, Cloud Map |
161| Identity & security | IAM, Cognito, KMS, Secrets Manager |
162| Config & ops | SSM Parameter Store, AppConfig, CloudWatch Logs, SES |
163
164Resources without local emulation run against the real cloud in
165your personal [stage](/environments/stages) — a stack that mixes
166emulated and live-only resources just works.
167
168## Mix in the real cloud
169
170`Alchemy.remote()` opts any resource out of local emulation:
171
172```typescript
173// everything else is local; this one hits real AWS
174const secret = yield* AWS.SecretsManager.Secret("ProdSecret", { ... })
175 .pipe(Alchemy.remote());
176```
177
178If a remote resource needs credentials you don't have,
179`alchemy dev` tells you before touching anything:
180
181```text
182AWS credentials are required, but none are configured for profile 'default'.
183These resources require AWS credentials:
184 - ProdSecret (runs against the real cloud via Alchemy.remote())
185Run `alchemy profile edit --profile default --add AWS` to configure credentials, or set CI=1 to use environment-variable credentials.
186```
187
188Switching a resource between local and live (or dev → deploy)
189plans a **replacement** — dev state never silently becomes cloud
190state. See
191[Local development](/environments/local-development) for the
192shared semantics.
193
194## Emulator management
195
196The emulator container outlives dev sessions — Docker is the
197supervisor, so there's nothing to babysit. Overrides when you
198want them:
199
200```sh
201ALCHEMY_FLOCI_IMAGE=floci:dev alchemy dev # use your own emulator build
202```
203
204The default image is our patched release
205(`ghcr.io/alchemy-run/floci`).
206
207To wipe everything inside the emulator without recreating the
208container, point [`nuke`](/cli/nuke) at the local providers:
209
210```sh
211bun alchemy unsafe nuke --local --include 'AWS.*'
212```
213
214`--local` enumerates and deletes through each provider's local
215implementation, so it only ever sees emulated resources — no
216cloud credentials are involved and nothing in a real AWS account
217can be touched.
218
219## Test against the local stack
220
221The [test harness](/testing/test-harness) has the same dev mode —
222`Test.make({ dev: true })` (available on both the Bun and Vitest
223adapters, off by default) runs the suite's `deploy(Stack)` against
224the local emulator instead of the real account, no separate
225`alchemy dev` terminal needed:
226
227```typescript
228const { test, beforeAll, afterAll, deploy, destroy } = Test.make({
229 providers: AWS.providers(),
230 dev: true,
231});
232```
233
234Lambda functions run in local containers, the emulated services
235back them, and function URL outputs point at the local gateway —
236so the same HTTP assertions run with zero cloud credentials. See
237[Test harness → dev](/testing/test-harness#dev) for the full
238semantics.
239
240## Where next
241
242- [Local development](/environments/local-development) — the
243 shared `alchemy dev` concepts: hot reload, `Alchemy.remote()`,
244 and dev vs deploy semantics.
245- [AWS frontends](/aws/frontend/websites) — framework dev servers
246 under `alchemy dev`.
247- [Stages](/environments/stages) — how live-in-dev resources stay
248 isolated per developer.
249- [Testing](/testing) — run the same test suite against the local
250 emulator with `Test.make({ dev: true })`.
251- [Local Providers](/infrastructure-as-code/local-provider) —
252 build the local implementation of a resource.