DEV Community

Cover image for Message Queues Explained Using a Cafe Example
Khushi Patel
Khushi Patel

Posted on

Message Queues Explained Using a Cafe Example

What Is a Message Queue?

Imagine a busy café during lunch time. Many customers place orders at
once, but the café has only four chefs. If the cashier had to wait for a
chef to finish every order before accepting the next one, the line would
move very slowly.

Instead, the cashier writes each order on a ticket and puts it on a
rack. The chefs pick up tickets when they are ready to cook. The cashier
can keep accepting orders while the chefs work through the queue.

That ticket rack is like a message queue in software: it temporarily
stores tasks or messages so the sender and receiver do not need to work
at exactly the same time.

Map the Café to Software

Café Software


Customer's order Message or task
Cashier who creates the ticket Producer
Ticket rack Message queue
Chef who picks up a ticket Consumer or worker
Preparing the order Processing the message
Finished order Successfully processed message

How Does a Message Queue Work?

  1. A producer creates a message, such as "send an order confirmation email."
  2. The producer sends the message to the queue.
  3. The queue stores it until a consumer is ready.
  4. A consumer receives the message and performs the task.
  5. After successful processing, the consumer acknowledges the message so the queue knows it has been handled. The exact acknowledgement and deletion behavior depends on the queue technology and configuration.

The important point is that the producer usually does not have to wait
for the full task to finish.

When Should You Use a Message Queue?

1. When a Task Can Happen in the Background

After a customer places an order, the website should confirm the order
quickly. Sending an email, generating an invoice, and notifying the
warehouse can happen in the background.

Without a queue: The customer request may wait for every task to
finish.

With a queue: The order service saves the order and schedules
follow-up tasks. Background workers process those tasks separately.

Use this when the user does not need to wait for the entire task to
complete.

2. When Traffic Arrives in Sudden Bursts

Imagine 200 orders arrive in one minute, but your workers can process
only 80 orders per minute.

The queue can temporarily hold the extra work. Workers keep processing
at their available rate, and the backlog shrinks when incoming traffic
slows.

A queue buffers traffic; it does not magically increase processing
capacity
. If messages arrive faster than they can be processed for a
long time, the backlog will continue growing. You may need more workers,
faster processing, rate limits, or a capacity change.

3. When Two Services Should Not Depend on Each Other Being Available at the Same Time

Suppose your order service is working, but your email service is
temporarily down. A queue can retain email tasks so they can be retried
when the email service recovers, depending on your queue setup.

This reduces the need for the order service to wait for every downstream
service to be available.

4. When You Need Retries for Temporary Failures

A worker might fail because of a temporary network problem or an
unavailable external API. A queue system can support retrying the
message.

Retries should usually have a limit and a delay strategy. After repeated
failures, the message can be moved to a dead-letter queue for
investigation instead of retrying forever.

5. When You Need to Process Many Independent Jobs

Examples include resizing uploaded images, generating reports,
processing payments through a carefully designed workflow, importing
files, sending notifications, or running data pipelines.

Queues are useful when work can be split into independent jobs and
processed by one or more workers.

When Might You Not Need a Message Queue?

  • The result is needed immediately. If a user asks for their current account balance, the application usually needs to fetch the current result synchronously.
  • The operation is simple and fast. Adding a queue can create extra infrastructure and complexity without much benefit.
  • You need an immediate, definitive response. A queue often means the request is accepted for later processing, not that the work has already succeeded.
  • You cannot safely handle duplicate processing. Many queue systems can deliver a message more than once. Design consumers to be idempotent, meaning processing the same message again does not create an unwanted duplicate effect.

A system can combine both approaches: respond synchronously for the
critical result, then queue non-critical follow-up tasks.

How to Use a Message Queue in a Real Application

Step 1: Identify the Work That Can Be Done Later

Start with a task that does not need to finish before the user receives
the main response. For example: send a confirmation email after an order
is saved.

Step 2: Choose a Queue Technology

Common options include:

  • RabbitMQ: Often used for task queues and routing messages between services.
  • Apache Kafka: Often used for high-volume event streams, durable event logs, and consumers that may need to read or replay events.
  • Cloud-managed queues: Services such as Amazon SQS or Google Cloud Pub/Sub can reduce the work of managing queue infrastructure.

Choose based on your delivery, ordering, throughput, replay, hosting,
and operational requirements rather than popularity alone.

Step 3: Create a Clear Message Format

Keep messages structured and versionable. For example:

{
  "eventType": "OrderPlaced",
  "orderId": "ORD-1042",
  "createdAt": "2026-10-19T12:00:00Z"
}
Enter fullscreen mode Exit fullscreen mode

Avoid putting unnecessary personal or sensitive data in messages. Often,
an identifier such as orderId is enough for a worker to retrieve the
required details securely.

Step 4: Publish the Message

After the order is saved, the order service publishes an OrderPlaced
message. In production systems, think carefully about what happens if
the database save succeeds but publishing the message fails. A common
solution is the transactional outbox pattern, which records the
event in the same database transaction and publishes it reliably
afterward.

Step 5: Build a Consumer or Worker

A separate worker subscribes to or polls the queue, reads the message,
performs the task, and acknowledges success according to the
technology's rules.

For example, an email worker reads the order ID, fetches the order
details, and sends the confirmation email.

Step 6: Make Processing Safe to Retry

A worker can finish its task but fail before its acknowledgement reaches
the queue. The message may then be delivered again.

Use idempotency where possible. For example, store a unique task or
event ID and check whether the email or operation has already been
completed before repeating it. For payments and other critical
operations, use the payment provider's idempotency mechanisms and
carefully designed state transitions.

Step 7: Monitor the Queue

Track: - Number of messages waiting - Age of the oldest message -
Processing rate and failure rate - Retry count and dead-letter queue
size - Consumer health and processing latency

A growing queue can mean traffic has increased, workers are failing, or
processing has become too slow.

Important Concepts to Know

Producer

The component that creates and sends messages. In our café, it is the
cashier placing order tickets on the rack.

Consumer

The component that receives and processes messages. In our café, it is a
chef picking up a ticket.

Acknowledgement

A signal that a message has been processed successfully. The queue's
acknowledgement rules determine when a message can be considered
complete.

Retry

An attempt to process a message again after a temporary failure. Use
bounded retries and appropriate delays.

Dead-Letter Queue

A separate destination for messages that repeatedly fail, allowing
investigation without blocking the normal flow.

Idempotency

The ability to process the same message more than once without causing
the same real-world effect multiple times. This matters because many
systems provide at-least-once delivery, not a guarantee that each
message is delivered exactly once.

Ordering

Some applications require messages to be processed in order, such as
updates to the same account. Ordering guarantees depend on the queue
technology and configuration and may reduce parallelism.

Example: An Online Shopping Order

A customer clicks Place Order.

  1. The order service validates and saves the order.
  2. It publishes an OrderPlaced event.
  3. Separate consumers handle tasks such as sending an email, creating an invoice, notifying the warehouse, and updating analytics.
  4. If the email service is temporarily unavailable, the email task can be retried without requiring the customer to submit the order again.
  5. The system monitors pending messages and failures so problems are visible.

For critical workflows, do not assume that sending a message alone
completes a payment or guarantees delivery. Track each step's status and
design recovery behavior.

Quick Interview Question

Question: Your application receives 200 jobs per minute, but workers
can process only 80 jobs per minute. What happens when you add a message
queue?

Answer: The queue stores the jobs that workers cannot process
immediately, so the application can absorb a short burst. The workers
still process only about 80 jobs per minute. If the incoming rate stays
at 200 per minute, the backlog grows by roughly 120 jobs per minute
until capacity increases or incoming traffic falls.

Follow-up: What would you do if the queue keeps growing?

Possible answers: add more consumers if the work can be parallelized,
optimize slow processing, apply rate limits or backpressure, and
investigate errors or downstream bottlenecks.

Key Takeaway

A message queue is like the café's ticket rack. The producer adds work,
the queue holds it, and consumers process it when they are ready. Use
queues for background work, traffic bursts, service decoupling, and
retryable jobs---but plan for failures, duplicate delivery, monitoring,
and growing backlogs.

Top comments (0)