Sitemap

Message Queue — Fundamentals to Advanced

2 min readJun 13, 2025

--

                   ┌────────────┐
│ 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)

--

--

Ritik Chourasiya
Ritik Chourasiya

Written by Ritik Chourasiya

I’m a 22 year old, still undergraduate backend developer based in India, with 2 years of experience in the software development industry.

No responses yet