Message Queue
One service puts messages into a message queue, and another service picks them up and processes them at its own speed - point-to-point, one message to one consumer.
24.1 Why is it used?
- If you do email, invoice and inventory all synchronously the moment an order is placed, the user waits 5 seconds; put it in a queue and respond immediately.
- If 1 lakh orders/minute arrive on sale day and the payment service can handle only 20 thousand, the queue becomes a buffer (load leveling).
- Producer and consumer are decoupled - even if a consumer is down, the message stays safe in the queue and is processed later.
- By adding consumers (horizontal scaling) you can finish the work faster in parallel.
24.2 How it works
- Point-to-point: one message goes to only one consumer; with multiple consumers the work is shared among them (competing consumers).
- Acknowledgement (ack): the consumer processes and sends an ack, and only then is the message deleted; if no ack arrives the message is delivered again.
- Visibility timeout (SQS): after a message is picked up it is hidden from others for a while; if it is not deleted in time it becomes visible again.
- Dead Letter Queue (DLQ): a message that keeps failing (e.g. 5 retries) is moved to a separate DLQ so the queue does not block and you can debug later.
- Delivery guarantee: most queues give at-least-once, so the consumer must be idempotent (no problem even if the same message arrives twice).
- Ordering: Standard SQS has no order guarantee; SQS FIFO or a RabbitMQ single queue + single consumer maintains order.
- Durability: in RabbitMQ a durable queue + persistent message is saved on disk, so data survives a broker restart.
- Prefetch / batch: how many messages a consumer takes at once (RabbitMQ prefetch count, SQS max 10 per receive) - balances throughput and fairness.
- 1.Sale day users: 50,000 orders/min
- 2.Order Service: saves to the order DB + enqueues, user instantly sees 'Order confirmed' (no wait for email)
- 3.SQS order-placed: queue depth = load buffer
- 4.Invoice worker 1 ... worker 20: each message goes to only ONE worker, deleted (ack) after processing
- 5.Fails 5 times (maxReceiveCount = 5): order-placed-DLQ, CloudWatch alarm alerts the team, redrive after the fix
- 6.Queue depth rises: Auto Scaling starts new workers, scales back after the sale
- 1.Worker 3 receives: msg hidden from others (visibility timeout = 60 sec)
- 2.Worker 3 crashes: no ack / delete
- 3.60 sec up: timeout over, msg visible again
- 4.Worker 7 receives: the same msg again
- 5.Process + delete: after the ack it is removed from the queue for good
At-least-once -> duplicates can arrive: make the consumer idempotent (order_id already processed? then skip, no double charge). Visibility timeout must not be shorter than processing time: otherwise the msg is still being processed and another worker picks it up too. Need ordering? SQS FIFO or a RabbitMQ single queue + single consumer. Need replay / lakhs of msg/sec? Look at Kafka
24.3 Tools you can use
| Tool | Type | How it is used |
|---|---|---|
| RabbitMQ | Open-source message broker (AMQP) | Flexible routing with exchange + queue + routing key; ack, DLX (dead letter exchange), priority queue support. |
| AWS SQS | Managed queue (AWS) | Fully managed, auto scale; Standard (unlimited throughput, at-least-once) and FIFO (ordered, exactly-once processing) queues, built-in DLQ redrive. |
| Apache ActiveMQ | Open-source JMS broker | Common in older Java/JMS-based enterprise apps; a managed version is available as AWS Amazon MQ. |
| Azure Service Bus | Managed broker (Azure) | Queues + topics, sessions (ordering), a built-in dead-letter sub-queue, transactions - for enterprise workloads. |
| Google Cloud Tasks | Managed task queue (GCP) | Dispatches tasks to an HTTP endpoint with rate limit and retry - for simple async work on GCP. |
24.4 Comparison: RabbitMQ vs AWS SQS vs Azure Service Bus
| Point | RabbitMQ | AWS SQS | Azure Service Bus |
|---|---|---|---|
| Hosting | You run it (or CloudAMQP / Amazon MQ) | Fully managed, serverless | Fully managed Azure service |
| Routing | Very flexible: direct, topic, fanout, headers exchange | Simple queue; combine with SNS for fanout | Queues + topics/subscriptions with filters |
| Ordering | FIFO in a single queue (with a single consumer) | Standard: no guarantee; FIFO queue: guaranteed per group | Ordered processing via sessions |
| DLQ | Configure a Dead Letter Exchange (DLX) | Redrive policy: DLQ after maxReceiveCount | Built-in dead-letter sub-queue in every queue |
| Latency | Very low (ms or less) | Somewhat higher (polling based, tens of ms) | Low, tens of ms |
| Scaling | You must manage the cluster | Automatic, almost unlimited (Standard) | Scales via tiers/messaging units |
| Cost | Server cost + an ops team | Pay per request, cheap at small load | Tier based pricing |
| Best for | Complex routing, on-prem, low latency | Simple, reliable decoupling on AWS | Azure enterprise apps, transactions |
24.5 When to choose which
- AWS SQS: when you are on AWS and want a simple reliable queue without managing servers.
- RabbitMQ: when you need complex routing (topic/fanout), very low latency, or on-prem/multi-cloud.
- Azure Service Bus: enterprise apps on the Azure stack that need sessions and transactions.
- ActiveMQ / Amazon MQ: when migrating older JMS-based Java apps.
- If you need replay, very high throughput (lakhs of msg/sec) and multiple consumers, look at Kafka (event streaming), not a queue.
24.6 Real-world example
A hypothetical scenario: order processing on an e-commerce sale day
- As soon as the sale starts, 50,000 orders/minute arrive; the Order Service saves the order in the DB and puts a message on the SQS 'order-placed' queue.
- The user instantly sees 'Order confirmed' and does not wait for the email/invoice.
- 20 Invoice workers pick messages from the queue (competing consumers); each worker processes its message and then deletes (acks) it.
- If a worker crashes, that message goes to another worker after the visibility timeout (e.g. 60 sec).
- If an order's data is bad and it fails 5 times, the redrive policy sends it to order-placed-DLQ.
- A CloudWatch alarm alerts the team when a message lands in the DLQ; after the fix it is sent back to the main queue via DLQ redrive.
- When queue depth rises, Auto Scaling starts new workers, and scales back after the sale.
24.7 Interview tips
- Common mistake: not making the consumer idempotent - with at-least-once delivery a duplicate message will arrive and the customer may be charged twice.
- Common mistake: having no DLQ - one 'poison message' keeps failing and slows the whole queue. Setting the visibility timeout shorter than processing time is also wrong - the message is still being processed and another worker picks it up too.
- Interview tip: state the queue vs pub/sub difference - in a queue one message goes to one consumer, in pub/sub every subscriber gets a copy.
- Worth quoting: SQS Standard is at-least-once with no ordering, FIFO orders per group; DLQ after maxReceiveCount (e.g. 5); SQS receives at most 10 messages per call.