Skip to content

🧠 What is RabbitMQ (in simple words)?

RabbitMQ is a message broker.

πŸ‘‰ It sits between services and safely stores messages until another service is ready to process them.

Think of it like WhatsApp for services:

  • Producer = sender
  • RabbitMQ = WhatsApp server
  • Consumer = receiver

🧩 Why do we need RabbitMQ?

Without RabbitMQ:

Frontend β†’ Backend β†’ Email Service

❌ If Email Service is down β†’ request fails

With RabbitMQ:

Frontend β†’ Backend β†’ RabbitMQ β†’ Email Service

βœ… Backend continues, email is sent later

Key Benefits

  • Decouples services
  • Handles traffic spikes
  • Reliable message delivery
  • Async processing
  • Retry & failure handling

πŸ— RabbitMQ Core Concepts (VERY IMPORTANT)

Image

Image

Image

1️⃣ Producer

App that sends messages

2️⃣ Consumer

App that receives messages

3️⃣ Queue

  • Stores messages
  • FIFO (First In, First Out)

4️⃣ Exchange

  • Decides where messages go
  • Producers never send directly to queues

5️⃣ Binding

  • Rule that connects Exchange β†’ Queue

πŸ” Types of Exchanges (Interview Favorite)

Exchange Use case
Direct Exact routing
Fanout Broadcast
Topic Pattern-based routing
Headers Header matching

We’ll use Direct first (easiest).


πŸš€ Step 1: Run RabbitMQ using Docker (Best for learning)

docker run -d \
  --name rabbitmq \
  -p 5672:5672 \
  -p 15672:15672 \
  rabbitmq:3-management

Access UI

πŸ‘‰ http://localhost:15672 Username: guest Password: guest


πŸ–₯ RabbitMQ Management UI (Must Know)

Image

Image

Image

You can:

  • Create queues
  • Create exchanges
  • Bind queues
  • Monitor messages
  • See consumers

πŸ§ͺ Step 2: Create Queue & Exchange (Manual – for understanding)

  1. Go to Exchanges
  2. Create exchange:

  3. Name: order_exchange

  4. Type: direct
  5. Go to Queues
  6. Create queue:

  7. Name: order_queue

  8. Bind:

  9. Exchange β†’ Queue

  10. Routing key: order.created

πŸ§‘β€πŸ’» Step 3: Producer (Node.js)

Install dependency

npm init -y
npm install amqplib

producer.js

const amqp = require("amqplib");

async function sendMessage() {
  const connection = await amqp.connect("amqp://localhost");
  const channel = await connection.createChannel();

  const exchange = "order_exchange";
  const routingKey = "order.created";
  const message = {
    orderId: 123,
    product: "Laptop",
    price: 90000
  };

  await channel.assertExchange(exchange, "direct", { durable: true });

  channel.publish(
    exchange,
    routingKey,
    Buffer.from(JSON.stringify(message)),
    { persistent: true }
  );

  console.log("Order sent:", message);

  setTimeout(() => {
    connection.close();
    process.exit(0);
  }, 500);
}

sendMessage();

Run:

node producer.js

πŸ‘‚ Step 4: Consumer (Node.js)

consumer.js

const amqp = require("amqplib");

async function consume() {
  const connection = await amqp.connect("amqp://localhost");
  const channel = await connection.createChannel();

  const queue = "order_queue";
  await channel.assertQueue(queue, { durable: true });

  channel.consume(queue, (msg) => {
    if (msg) {
      const data = JSON.parse(msg.content.toString());
      console.log("Received order:", data);

      // simulate processing
      setTimeout(() => {
        channel.ack(msg);
      }, 1000);
    }
  });
}

consume();

Run:

node consumer.js

βœ… You’ll see messages flowing πŸŽ‰


πŸ” Step 5: Message Acknowledgment (VERY IMPORTANT)

Type Meaning
ack Message processed successfully
nack Failed, requeue or drop
no ack ❌ Risky (message loss)

Example:

channel.nack(msg, false, true); // retry

πŸ’€ Step 6: Dead Letter Queue (DLQ)

For failed messages after retries.

Create DLX

order_dlx
order_dlq

Queue config

channel.assertQueue("order_queue", {
  durable: true,
  arguments: {
    "x-dead-letter-exchange": "order_dlx"
  }
});

πŸ’‘ Failed messages move to DLQ instead of being lost.


⚑ Step 7: Competing Consumers (Scaling)

Run consumer multiple times:

node consumer.js
node consumer.js
node consumer.js

RabbitMQ will load balance messages automatically.


⏱ Step 8: Prefetch (Prevent Overload)

channel.prefetch(1);

πŸ‘‰ One message at a time per consumer πŸ‘‰ Prevents memory overload


πŸ”„ Step 9: Retry Pattern (Production Ready)

Queue β†’ Retry Queue β†’ Main Queue

Use TTL + DLX for delayed retries.


πŸ“¦ Common Real-World Use Cases

Use Case Pattern
Email sending Async queue
Payment processing Reliable delivery
Log processing Fanout
Notifications Topic
Microservices Event-driven

🧠 RabbitMQ vs Kafka (Quick Clarity)

RabbitMQ Kafka
Task queue Event streaming
Low latency High throughput
Easier More complex
Per-message ack Offset-based

πŸ‘‰ Use RabbitMQ for backend jobs πŸ‘‰ Kafka for analytics / streams


πŸš€ Production Best Practices

βœ… Use durable queues βœ… Use persistent messages βœ… Enable ack βœ… Use DLQ βœ… Monitor via UI / Prometheus βœ… Don’t use guest in prod βœ… Separate vhosts per app


version: "3"
services:
  rabbitmq:
    image: rabbitmq:3-management
    ports:
      - "5672:5672"
      - "15672:15672"
docker compose up -d

🧭 What You Should Learn Next

  1. Topic exchange
  2. Retry queues
  3. Delayed messages
  4. Priority queues
  5. Security (users, vhosts)
  6. RabbitMQ + Kubernetes
  7. RabbitMQ + OpenTelemetry

βœ… Final Mental Model

Producer
   ↓
Exchange (rules)
   ↓
Queue (store)
   ↓
Consumer (process)