1---
2title: 2.0.0-beta.60 - Docker, MicroVMs & RSC
3date: 2026-07-06T22:00:00Z
4category: release
5excerpt: v2.0.0-beta.60 adds a Docker provider, AWS Lambda MicroVMs, Workers for Platforms, React Server Components on Vite, class-based Workflows on async Workers, dramatically faster Cloudflare Container starts, and a ground-up docs overhaul.
6---
7
8beta.60 is a big one: a new **Docker provider**, **AWS Lambda
9MicroVMs**, **Workers for Platforms**, **React Server Components**
10on the Vite pipeline, class-based **Workflows on async Workers**,
11Cloudflare **Containers** that start fast and stay up, and a
12ground-up overhaul of the docs. No breaking changes this release.
13
14## Docker provider
15
16`alchemy/Docker` brings `Image`, `RemoteImage`, `Container`,
17`Volume`, and `Network` as Stack resources
18([#649](https://github.com/alchemy-run/alchemy/pull/649)).
19They drive the `docker` CLI's active context — Docker Desktop, a
20remote/SSH context, a CI daemon — and live in the same Stack as
21your cloud resources. Thanks **Austin**!
22
23```typescript
24const image = yield* Docker.RemoteImage("postgres-image", {
25 name: "postgres",
26 tag: "18-alpine",
27});
28const network = yield* Docker.Network("app-network");
29const data = yield* Docker.Volume("postgres-data");
30
31const postgres = yield* Docker.Container("postgres", {
32 image,
33 environment: { POSTGRES_PASSWORD: password }, // Redacted-safe
34 ports: [{ external: 15432, internal: 5432 }],
35 volumes: [{ hostPath: data.name, containerPath: "/var/lib/postgresql/data" }],
36 networks: [{ name: network.name, aliases: ["postgres"] }],
37 start: true,
38});
39```
40
41Secrets are passed via process env (never on the CLI), pulled tags
42are pinned so re-deploys are no-ops, and containers created outside
43alchemy follow the standard adoption rules. See the new
44[Docker hub](/docker) and the
45[local services guide](/docker/local-services).
46
47## AWS Lambda MicroVMs
48
49`AWS.Lambda.MicrovmImage` is a new Platform for snapshot-booted
50microVMs ([#712](https://github.com/alchemy-run/alchemy/pull/712)).
51Author the in-VM server in TypeScript — alchemy bundles it,
52generates the Dockerfile, and builds the snapshot server-side — or
53bring your own Dockerfile or a prebuilt artifact:
54
55```typescript
56export class Sandbox extends AWS.Lambda.MicrovmImage<
57 Sandbox,
58 { hello: (message: string) => Effect.Effect<string> }
59>()("Sandbox") {}
60
61export default Sandbox.make(
62 { main: import.meta.filename, buildRole },
63 Effect.gen(function* () {
64 return {
65 hello: (message) => Effect.succeed(`hello, ${message}!`),
66 fetch: Effect.gen(function* () { /* raw HTTP route */ }),
67 };
68 }),
69);
70```
71
72Every instance operation — `RunMicrovm`, `GetMicrovm`,
73suspend/resume/terminate, auth tokens, image builds — is a
74`Binding.Service` with least-privilege IAM scoping, and
75`connectMicrovm` gives you typed RPC into the running VM:
76
77```typescript
78const sandbox = yield* AWS.Lambda.connectMicrovm(Sandbox, { endpoint, authToken });
79const reply = yield* sandbox.hello("world");
80```
81
82It works cross-cloud too: binding a MicroVM operation from a
83`Cloudflare.Worker` mints an IAM user + assume-role Role so the
84Worker can drive AWS MicroVMs at runtime.
85
86We also benchmarked MicroVMs against Cloudflare Containers — 700
87isolated cold boots. MicroVMs boot in 2–4.5s regardless of what's
88inside; full results in
89[Benchmarking Cloudflare Containers vs AWS MicroVMs](/blog/2026-07-01-microvm-cold-starts).
90Docs: [MicroVMs](/aws/compute/microvms).
91
92## Workers for Platforms
93
94Deploy user Workers into a dispatch namespace and route to them
95dynamically ([#715](https://github.com/alchemy-run/alchemy/pull/715)).
96A Worker deploys *into* a namespace with the new `namespace` prop —
97no duplicate resource type:
98
99```typescript
100const ns = yield* Cloudflare.WorkersForPlatforms.DispatchNamespace("Customers", {});
101
102const userWorker = yield* Cloudflare.Worker("CustomerA", {
103 namespace: ns.name,
104 script: `export default { fetch() { return new Response("hi") } }`,
105});
106```
107
108The platform Worker binds the namespace Effect-natively, or via
109`env` for async Workers:
110
111```typescript
112// Effect-native — yield the binding, get a typed client
113const dispatch = yield* Cloudflare.WorkersForPlatforms.Get(namespace);
114const userWorker = yield* dispatch.get("customer-a");
115```
116
117```typescript
118// async — DispatchNamespace is a valid env binding
119const platform = Cloudflare.Worker("Platform", {
120 main: "./handler.ts",
121 env: { DISPATCH: namespace },
122});
123// handler.ts: env.DISPATCH.get("customer-a").fetch(request)
124```
125
126Docs: [Workers for Platforms](/cloudflare/compute/workers-for-platforms).
127
128## React Server Components on Vite
129
130`Cloudflare.Vite` now supports builds that emit more than one
131server environment — most notably RSC
132([#685](https://github.com/alchemy-run/alchemy/pull/685)).
133`viteEnvironments` selects which environment produces the deployed
134Worker entry and which additional server environments are bundled
135alongside it:
136
137```typescript
138const app = yield* Cloudflare.Vite("ReactRouterRSC", {
139 compatibility: { flags: ["nodejs_compat"] },
140 viteEnvironments: { entry: "rsc", children: ["ssr"] },
141});
142```
143
144A single-environment SSR build needs no configuration — the
145default is `{ entry: "ssr", children: [] }` — and the `client`
146environment always deploys as static assets. The same PR replaces
147the dev-server restart fingerprint with an exact structural
148signature, so config changes are never silently missed. Docs:
149[Frontends on Cloudflare](/cloudflare/frontend/frontends).
150
151## Workflows on async Workers
152
153Class-based Cloudflare Workflows now bind to async (non-Effect)
154Workers via `env`, mirroring class-based Durable Objects
155([#707](https://github.com/alchemy-run/alchemy/pull/707)):
156
157```typescript
158export const AsyncWorker = Cloudflare.Worker("Async", {
159 main: "./src/worker.ts",
160 env: {
161 MY_WORKFLOW: Cloudflare.Workflow<{ value: string }>("MyWorkflow", {
162 className: "MyWorkflow",
163 }),
164 },
165});
166export type Env = Cloudflare.InferEnv<typeof AsyncWorker>;
167// env.MY_WORKFLOW is the native Workflow<{ value: string }>
168```
169
170Your `WorkflowEntrypoint` class stays plain `cloudflare:workers`
171code; alchemy provisions the workflow and emits the binding.
172Cross-script references work with `scriptName`, same as async DOs.
173Docs: [Workflows](/cloudflare/compute/workflows).
174
175## Containers start fast and stay up
176
177Cloudflare Containers deployed with alchemy behaved much worse
178than the same image deployed with wrangler — at 100 concurrent
179cold starts, ~2/100 succeeded. Two root causes, both fixed
180([#708](https://github.com/alchemy-run/alchemy/pull/708)):
181
182- **Wrangler-parity defaults** — `maxInstances` defaulted to `1`,
183 serializing every Durable Object through one container slot. Now
184 `maxInstances: 20`, scale-from-zero, and `instanceType: "lite"`
185 when no custom limits are set, matching wrangler.
186- **Readiness polling** — probes had no per-probe timeout, so a
187 not-yet-listening port could hang for minutes. The loop now
188 mirrors `@cloudflare/containers` exactly.
189
190Result: 100/100 cold starts, on par with wrangler. And a container
191that stops or crashes is now transparently restarted on the next
192request, while a crash-looping container fails fast instead of
193burning the readiness budget
194([#711](https://github.com/alchemy-run/alchemy/pull/711)).
195Docs: [Containers](/cloudflare/compute/containers).
196
197## Effectful compute on ECS and EC2
198
199The `ServerHost` + `{ fetch }` pattern now works end to end on
200`AWS.ECS.Task`
201([#713](https://github.com/alchemy-run/alchemy/pull/713)):
202the container entry bundles a Bun HTTP server, ships every chunk
203into the image, and builds for the architecture the task declares
204— verified by a smoke test that deploys a real Fargate service
205behind an ALB.
206
207The hosted `AWS.EC2.Instance` serves HTTP the same way, with a
208reboot-safe systemd unit that self-heals transient boot failures
209([#714](https://github.com/alchemy-run/alchemy/pull/714)).
210And there's a new `AWS.EC2.KeyPair` resource — the generated
211private key is captured once as a `Redacted` secret:
212
213```typescript
214const keyPair = yield* AWS.EC2.KeyPair("DeployKey", { keyType: "ed25519" });
215// keyPair.keyName -> AWS.EC2.Instance({ keyName })
216// keyPair.privateKey -> Redacted<string>
217```
218
219## The docs got a ground-up overhaul
220
221The website is restructured into per-provider hubs behind a
222horizontal tab bar — `Core · CLI · Cloudflare · AWS · PlanetScale ·
223Neon · More ▾` — with ~100 new or reworked pages
224([#721](https://github.com/alchemy-run/alchemy/pull/721)):
225
226- **Core** — Infrastructure as Code, Infrastructure as Effects,
227 APIs, Environments, State Store, Project structure, Testing.
228- **CLI** — every command documented, including the first-ever
229 docs for `alchemy unsafe nuke` and adopting resources.
230- **Cloudflare / AWS hubs** — setup, five-part tutorials, block
231 pages and guides grouped by role (Compute, Frontend, APIs, Data,
232 Messaging, AI, …).
233- Every page written against source, tests, and fixtures; every
234 moved URL 301s.
235
236Start at [the docs](/) and pick your provider.
237
238## Also in this release
239
240- **`--yes` is fully non-interactive**
241 ([#728](https://github.com/alchemy-run/alchemy/pull/728)) —
242 `alchemy deploy --yes` now auto-accepts the Cloudflare state
243 store upgrade and deploy prompts instead of hanging on a non-TTY,
244 so CI needs no workarounds.
245- **Partial state-store deploys are detected and recovered**
246 ([#700](https://github.com/alchemy-run/alchemy/pull/700)) —
247 the store health check now verifies a real store is serving, not
248 just that a pre-create stub exists.
249- **`Command.Build` memo includes command + env**
250 ([#738](https://github.com/alchemy-run/alchemy/pull/738)) —
251 two `StaticSite` builds differing only in env (per-stage
252 `EXPO_PUBLIC_*`, API ids) no longer reuse each other's output.
253- **Retained resources report as `retained`**
254 ([#739](https://github.com/alchemy-run/alchemy/pull/739)) —
255 destroy no longer lists `RemovalPolicy: "retain"` resources as
256 deleted. Thanks **bjorntechTobbe**!
257- **The CLI works on Windows**
258 ([#696](https://github.com/alchemy-run/alchemy/pull/696)) —
259 the stack entry loads via a `file://` URL. Thanks **d3lay**!
260- **Durable Object classes created outside alchemy adopt cleanly**
261 ([#495](https://github.com/alchemy-run/alchemy/pull/495)) —
262 class migrations fall back to matching the observed binding, so
263 adopting a wrangler/dashboard Worker reuses its DO classes
264 instead of failing to re-create them.
265- **Access Application survives state loss**
266 ([#742](https://github.com/alchemy-run/alchemy/pull/742)) —
267 `read` falls back to a domain scan and gates takeover behind
268 `--adopt`, instead of blindly creating a duplicate app with a
269 fresh `aud`. Thanks **Andy Jefferson**!
270- **Pooled connection origins** — Neon `Project`/`Branch`
271 ([#718](https://github.com/alchemy-run/alchemy/pull/718))
272 and PlanetScale `PostgresRole`
273 ([#717](https://github.com/alchemy-run/alchemy/pull/717))
274 expose `pooledOrigin`, and PlanetScale branch replica intent
275 persists so `replicas: 0` converges
276 ([#719](https://github.com/alchemy-run/alchemy/pull/719)).
277 Thanks **Alex**!
278- **AWS env-auth fixes** — `Region` is provided to STS during login
279 ([#709](https://github.com/alchemy-run/alchemy/pull/709))
280 and the `Region`/`AWSEnvironment` layer cycle in the account-id
281 lookup is broken
282 ([#710](https://github.com/alchemy-run/alchemy/pull/710)).
283
284## Where to go next
285
286- [Docker](/docker)
287- [MicroVMs](/aws/compute/microvms)
288- [Workers for Platforms](/cloudflare/compute/workers-for-platforms)
289- [Workflows](/cloudflare/compute/workflows)
290- [Benchmarking Cloudflare Containers vs AWS MicroVMs](/blog/2026-07-01-microvm-cold-starts)
291- [CHANGELOG](https://github.com/alchemy-run/alchemy/blob/main/CHANGELOG.md#v200-beta60)
292- [Compare v2.0.0-beta.59 → v2.0.0-beta.60](https://github.com/alchemy-run/alchemy/compare/v2.0.0-beta.59...v2.0.0-beta.60)