1---
2title: 2.0.0-beta.54 - Queues in Dev Mode
3date: 2026-06-10T22:00:00Z
4category: release
5excerpt: v2.0.0-beta.54 brings Cloudflare Queues and Queue Consumers to `alchemy dev` — produce and consume messages entirely on your machine, then let the first deploy upgrade the local queue to a live Cloudflare resource in place.
6---
7
8Cloudflare Queues now work end-to-end in `alchemy dev`. The local
9Cloudflare runtime emulates both the queue and its consumer, so the
10same Worker that produces and consumes messages in production runs
11unchanged on your laptop — send a message on one route and your
12consumer handler fires locally, no Cloudflare round-trip.
13
14## Queues and consumers in `alchemy dev`
15
16One Worker, both halves: `Cloudflare.Queue.bind` gives you the
17producer, `Cloudflare.messages(queue).subscribe` registers the
18consumer ([#571](https://github.com/alchemy-run/alchemy/pull/571)):
19
20```typescript
21export default class MyWorker extends Cloudflare.Worker<MyWorker>()(
22 "MyWorker",
23 { main: import.meta.filename },
24 Effect.gen(function* () {
25 const queue = yield* Cloudflare.Queue("MyQueue");
26 const producer = yield* Cloudflare.Queue.bind(queue);
27
28 // consumer — fires locally under `alchemy dev`
29 yield* Cloudflare.messages<{ text: string }>(queue).subscribe(
30 (stream) => Stream.runForEach(stream, (msg) => handle(msg.body)),
31 );
32
33 return {
34 fetch: Effect.gen(function* () {
35 const request = yield* HttpServerRequest.HttpServerRequest;
36 const body = yield* request.json;
37 yield* producer.send(body).pipe(Effect.orDie);
38 return yield* HttpServerResponse.json({ sent: body });
39 }),
40 };
41 }).pipe(
42 Effect.provide([
43 Cloudflare.QueueBindingLive,
44 Cloudflare.QueueEventSourceLive,
45 ]),
46 ),
47) {}
48```
49
50Under `alchemy dev`, the queue and consumer are provisioned by local
51providers: they get `dev:` IDs instead of live Cloudflare IDs, and the
52local runtime keeps its storage under `.alchemy/local`.
53
54On your first real `alchemy deploy`, the providers' diff logic
55recognizes the `dev:` ID and upgrades the resource **in place** — an
56update that creates the live queue and consumer under the same logical
57resource, never a replacement. And destroying a stack that only ever
58ran locally skips the Cloudflare API entirely.
59
60`QueueConsumer` also now persists `deadLetterQueue` and `settings`
61(batch size, concurrency, retries — see the new exported
62`QueueConsumerSettings` interface) in its attributes, so consumer
63config reconciles like everything else.
64
65## Also in this release
66
67- **`alchemy dev` no longer requires Cloudflare credentials at
68 startup** — the local runtime resolves the account ID lazily, only
69 when a live API call actually needs it
70 ([#578](https://github.com/alchemy-run/alchemy/pull/578)).
71- **PlanetScale providers are more resilient to live API timing** —
72 branch promote/demote retries while a cluster resize is still
73 finalizing, Postgres resizes wait for the branch to finish
74 provisioning first, and polling budgets grew from 10 to 30 minutes
75 (60 for Postgres cluster-size changes)
76 ([#576](https://github.com/alchemy-run/alchemy/pull/576)).
77
78## Where to go next
79
80- [Tutorial Part 4: Local Dev](/cloudflare/tutorial/part-4)
81- [Consume from a Queue](/cloudflare/messaging/queues)
82- [CLI reference](/cli)
83- [CHANGELOG](https://github.com/alchemy-run/alchemy/blob/main/CHANGELOG.md#v200-beta54)
84- [Compare v2.0.0-beta.53 → v2.0.0-beta.54](https://github.com/alchemy-run/alchemy/compare/v2.0.0-beta.53...v2.0.0-beta.54)