AV
HomeAboutProjectBlog

© 2026 Ave syah Shina. All rights reserved.

  1. Home
  2. Blog
  3. 08 — Queues: Asynchronous Message Processing at the Edge

08 — Queues: Asynchronous Message Processing at the Edge

August 13, 20267 min read
Download as Markdown

"Async Workers, somehow" was my Queues summary, and it didn't explain when or why to reach for one. The model that did: a queue is a buffer between a producer and a consumer that decouples them — it absorbs traffic spikes, retries failures, and paces work to whatever rate the consumer (or the backend behind it) can handle. [1] That decoupling is the entire point, and it's the answer to a class of problems that synchronous request/response can't solve.

The framing that landed is the failure mode it removes. When a Worker handles everything synchronously, two things break under load: a sudden spike of expensive work (image processing, email sending) ties up the request and either times out or burns the CPU budget; and a downstream dependency that's briefly unavailable fails the whole request, even though the work itself was valid. A queue fixes both. The producer enqueues a message in milliseconds and returns; the consumer processes at its own pace; a failed message retries instead of failing the user's request [1][2].

producer Worker enqueues & returns fast spike queue — buffer DLQ (failures) consumer Worker steady pace decoupled — producer returns fast, consumer paces itself at-least-once delivery · failures retry · poison messages divert to DLQ

Message processing: producer, consumer, at-least-once

The mechanics are straightforward. A producer (usually a Worker) sends messages to a queue with send or sendBatch. A consumer (another Worker, bound to the queue) receives batches of messages and processes them [2][3]. The delivery guarantee is at-least-once: a message will be delivered to the consumer at least once, even if there are failures. The consumer acknowledges successful processing to remove a message from the queue; if it crashes or throws before acknowledging, the message is redelivered.

That "at-least-once" wording is the part I had to take seriously, because it has a consequence: consumers must be idempotent. If the same message can arrive twice, processing it twice must not corrupt anything. A payment Worker that charges a card on each message is broken under at-least-once delivery; one that checks "has this message ID been processed yet?" before charging is correct. Designing for redelivery is the discipline that makes queues safe.

Background jobs

The canonical use case is moving expensive work out of the request/response cycle [4]. A user uploads an image; the upload Worker stores the raw file and enqueues a "process image" message; the user gets an immediate "uploaded, processing" response; a separate consumer Worker processes the image (resize, optimize, store derivatives) at its own pace. The user doesn't wait for the processing, the upload Worker stays within its CPU budget, and a spike of uploads becomes a deeper queue rather than a timeout storm.

Any task that's slow, bursty, or non-critical-to-the-current-request is a candidate: email sending, PDF generation, data export, webhook fanout, thumbnail creation. The decision rule: if the work doesn't need to block the response, it probably shouldn't.

Rate limiting

The less obvious use is using a queue to pace work [5]. Instead of hammering a downstream API or a backend directly, a producer enqueues every request; the consumer pulls from the queue at a controlled rate — say, 50 messages per second — matching the downstream's capacity. The queue absorbs the spikes; the downstream sees a steady, survivable load.

This is rate limiting as architecture rather than as rejection. A traditional rate limiter rejects requests over the limit; a queue-based one absorbs them and lets them through at the limit. The choice depends on whether the work needs to happen eventually (queue it) or right now (reject if over).

Dead letter queues

Not every message can be processed. A message whose payload is malformed, or that consistently throws in the consumer, would block the queue forever if there were no escape valve. That's the dead letter queue (DLQ) [6].

The pattern: after a configurable number of failed delivery attempts, a message is moved to a separate DLQ instead of being retried indefinitely. The main queue keeps flowing; the poison messages are quarantined for investigation. I then inspect the DLQ to find the underlying bug, fix the consumer, and reprocess or discard the messages deliberately.

The DLQ turns "a single broken message breaks the whole pipeline" into "a single broken message sits in a side queue waiting for me to look at it." That's the difference between a queue that survives production and one that doesn't.

How I use this

The shape I've settled on: any work that's slow, bursty, or downstream-of-something-fragile goes through a queue. The producer is thin (validate, enqueue, acknowledge), the consumer is idempotent (designed for at-least-once from day one), and every queue has a DLQ configured from the start — not as an afterthought. The single habit that's saved me the most pain is writing the consumer as if every message will arrive twice, because eventually one will.

References

[1] Cloudflare, "Cloudflare Queues," Cloudflare Docs, 2024. [Online]. Available: https://developers.cloudflare.com/queues/

[2] Cloudflare, "How does Queues work?," Cloudflare Docs, 2024. [Online]. Available: https://developers.cloudflare.com/queues/reference/how-queues-works/

[3] StackOverflow, "Difference between stream processing and message processing," community discussion. [Online]. Available: https://stackoverflow.com/questions/41744506/difference-between-stream-processing-and-message-processing

[4] Dispatched, "Background jobs for serverless applications," 2024. [Online]. Available: https://dispatched.dev/

[5] Cloudflare, "Cloudflare Queues — Queues & rate limits," Cloudflare Docs. [Online]. Available: https://developers.cloudflare.com/queues/tutorials/handle-rate-limits/

[6] AWS, "What is a dead-letter queue?," AWS Docs. [Online]. Available: https://aws.amazon.com/what-is/dead-letter-queue/

Knowledge check · Question 1 of 5

What delivery guarantee does Cloudflare Queues provide?

Comments

Leave a Comment

You must be signed in to comment

0 Comments

No comments yet. Be the first to comment!