Backend Development › Queues & Async Processing
Message Queue
A buffer where producers leave messages for consumers to process later.
Also known as: queue, message queues, MQ, queueing, SQS, RabbitMQ
A message queue is a buffer between producers (who send messages) and consumers (who process them). The producer drops a message in the queue and moves on, and a consumer picks it up when it’s ready. They don’t have to run at the same time, at the same speed, or know about each other.
Producer ─► [ m5 | m4 | m3 | m2 | m1 ] ─► Consumer
(web app) the queue (worker)
Examples of services and brokers: RabbitMQ, Amazon SQS, Google Cloud Pub/Sub, Azure Service Bus and others (message brokers).
What it gives you
- Decoupling: the sender doesn’t wait for, or depend on, the receiver being up.
- Smoothing load: a spike of requests piles up in the queue, and workers process it at a steady pace instead of falling over.
- Asynchronous work: send the email or generate the report in the background (background jobs).
- Scaling: add more consumers to drain the queue faster.
- Resilience: if a consumer crashes, the message is still there to be retried.
# Producer
queue.send({"type": "send_welcome_email", "user_id": 42})
# Consumer
while True:
msg = queue.receive()
send_welcome_email(msg["user_id"])
queue.ack(msg) # tell the broker it's done, so it can delete it
How it behaves
- In a classic queue, each message goes to one consumer (point-to-point). Compare with topics where every subscriber gets a copy (queue vs topic).
- The consumer acknowledges a message when done. No ack means it’s redelivered (acknowledgement, visibility timeout).
- Delivery is usually at-least-once, so handlers must be idempotent (at-least-once).
- Order is not always guaranteed, especially with several consumers (message ordering).
- Messages that keep failing go to a dead letter queue.
Things to watch
- Queue depth and message age. A growing queue means consumers aren’t keeping up (queue depth).
- Message size limits: put big data in storage, and send a reference.
- Added complexity: you now have a system to run, monitor and debug, and failures become asynchronous (harder to trace). Use a correlation ID.
- Not a database. Don’t use it for long-term storage or for querying data.
- Use a queue when work can be deferred and doesn’t need an immediate answer. If the caller needs the result now, make a direct call.