Queues guide
Background work with queues/*.ts producers and consumers — works on Outer today.
Verdict: works. Declare a queue file, send from anywhere, consume in batches. Standard Cloudflare Queues under the hood — no extra service.
1. Declare the queue
One file per queue under queues/; the path sets the name
(order/notifications.ts → order-notifications):
// queues/emails.ts
import { defineQueue } from "void";
export default defineQueue<{ to: string; subject: string }>(async (batch, env) => {
for (const msg of batch.messages) {
await sendDigest(env, msg.body); // your function
msg.ack();
}
});
export const maxBatchSize = 50;
export const maxBatchTimeout = 10;
export const maxRetries = 5;
export const retryDelay = 30;
Only one consumer may read a queue. Un-acked messages ack on success and
retry on throw (first call wins); over maxRetries they are permanently
deleted — Void configures no dead-letter queue.
2. Produce
import { queues } from "void/queues";
await queues.emails.send({ to, subject }); // typed from defineQueue<T>
Batches cap at 100 messages / 256 KiB total, one message at 128 KiB.
Delivery is at-least-once and unordered — key work by the stable msg.id
and keep consumers idempotent. Retention is 4 days.
3. Deploy
Bindings come from the built dist/wrangler.json: queues is an accepted
deploy key (crates/outer/src/deploy/pipeline.rs), so the queue deploys on
every account — plan gating for bindings arrives with billing. Rebuild after
editing queue files; consumers deploy with the app and scale with it.
Trigger local dispatch manually with the dev server’s POST /__void/queue
endpoint — queued messages don’t run on their own.
Sources
- Void queues guide: https://void.cloud/guide/queues
- Accepted wrangler keys:
crates/outer/src/deploy/pipeline.rs(ACCEPTED_CONFIG_KEYS) - celld queues: https://celld.dev/docs/services/queues