Message Queue — Fundamentals to Advanced
┌────────────┐
│ Producer │
└─────┬──────┘
│ Sends message
▼
┌─────────────┐
│ Message │
│ Broker │ RabbitMQ / Kafka
└─────┬───────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌────────────┐ ┌────────────┐
│ Consumer 1 │ │ Consumer 2 │ Competing workers
└────┬───────┘ └────┬───────┘
│ ACK/NACK │
▼ ▼
┌───────────────┐ ┌────────────────────┐
│ Ack: Done │ │ Nack: Retry or DLQ │
└───────────────┘ └────────────────────┘
/
/
/
┌───────────────┐
│ Dead Letter │
│ Queue │
└───────────────┘
🔍 1. Why Queues?
Queues solve a big problem in backend systems:
🔗 a. Decoupling
Without a queue:
Client → API → EmailService → SMTP → Success/Failure
➡ If SMTP fails, your whole flow breaks.
With a queue:
Client → API → Queue → EmailWorker → SMTP
✅ Your API responds fast; email gets processed eventually, even if SMTP is down briefly.
📊 b. Buffering
Imagine you get a spike of 100,000 orders at once.
Your DB or 3rd-party API may choke.
Queue acts like a traffic controller — storing tasks temporarily:
[100k Orders] → Queue → 10 workers → DB
♻️ c. Retry Mechanism
If a worker fails to send an email or write to DB, you can retry:
- After 5 sec
- Up to 3 times
- Then send to Dead Letter Queue (DLQ)
🚦 d. Backpressure Handling
Backpressure = system says “I can’t handle more right now.”
Queue helps:
- Accepts requests at high rate
- Workers pull at safe pace
- Prevents crashing under load
🧱 2. Key Terminology (with examples)
🧑💻 Producer
The app that sends messages to the queue.
channel.sendToQueue('email', Buffer.from(JSON.stringify({ to: "user@gmail.com" })));
👷 Consumer
The service that receives and processes messages.
channel.consume('email', (msg) => {
// send email
channel.ack(msg);
});+
🧠 Message Broker
The middleman that stores and routes messages.
Examples:
- RabbitMQ 🐰 (queues)
- Kafka 🐘 (topics + partitions)
- Redis Streams
- AWS SQS / SNS
It ensures:
- Delivery
- Routing (via exchange)
- Persistence (durable queues)
📬 Queue (RabbitMQ, Redis)
- FIFO (First-In-First-Out)
- Simple: each message is delivered to one consumer
- Good for background jobs, email, image processing
Queue: 'task_queue'
→ Worker1
→ Worker2 (competing consumers)
📢 Topic (Kafka)
- Supports publish/subscribe pattern
- One message can go to multiple consumers
- Each consumer group reads independently
Use case: Logging, real-time analytics
✅ 3. Message Acknowledgements
✅ ack()
: Acknowledge
- Message processed successfully
- Broker removes it from the queue
channel.ack(msg);
❌ nack()
or Reject
- Message failed
- Can either requeue or discard
channel.nack(msg, false, true); // requeue
💀 4. DLQ (Dead Letter Queue)
A special queue where messages go after:
- Too many retries
- Invalid format
- Consumer error
This lets you:
- Analyze failures later
- Avoid infinite retry loops
Example:
email_queue (→ retry x3)
↓
dead_letter_queue
💡 Real-World Analogy
Think of a queue like a restaurant order system:
- Customer (Producer): places an order
- Waiter (Message Broker): takes the order
- Kitchen (Consumer): prepares the dish
- Order Completed (ack): serve to customer
- If chef fails → retry → if fails again → log the issue (DLQ)