MESSAGING & EVENT-DRIVEN ARCHITECTURE / SYSTEM CONCEPT BRIEF

RabbitMQ

RabbitMQ is a message broker implementing AMQP.

IntermediatePhase 06 / Topic 4 of 18RequirementsTrade-offsFailure modes
01

Overview

RabbitMQ is a message broker implementing AMQP. Producers publish to exchanges, and exchanges route messages to queues using bindings: direct (exact routing key), topic (wildcard patterns), fanout (all bound queues), or headers. Consumers receive messages from queues and acknowledge them individually.

RabbitMQ shines at flexible routing, per-message acknowledgments, priorities, delayed and dead-lettered messages, and request-reply patterns. It is a traditional 'smart broker, simple consumer' design, whereas Kafka is 'simple broker, smart consumer' with retained logs.

A post office sorting room

Letters (messages) arrive at the sorting desk (exchange), which reads the address (routing key) and places each into the right mailboxes (queues) according to rules. Recipients pick up mail from their own boxes.

02

When to use it

  • Task queues with complex routing rules.
  • Per-message acks, retries, priorities, and TTLs.
  • Request-reply (RPC over messaging).
  • Moderate throughput with low latency.
03

Where it shows up in interviews

Routed work distribution

Recognize it when: different message types to different workers.

  • Design a notification router (SMS, email, push)
  • Design a job system with priorities
RPC over messaging

Recognize it when: request-reply between services asynchronously.

  • Design a background PDF render service
04

Where it is used in real software

Celery

Python's popular task queue commonly uses RabbitMQ as its broker.

Quorum queues

RabbitMQ's Raft-based replicated queues for high availability and data safety.

Amazon MQ and CloudAMQP

Managed RabbitMQ offerings.

05

Key terms

Exchange
Receives messages and routes them to queues.
Binding / routing key
Rule linking exchange to queue / label used for routing.
Direct / topic / fanout exchange
Exact match / wildcard pattern / broadcast.
Prefetch (QoS)
Max unacknowledged messages per consumer.
Dead-letter exchange
Where rejected or expired messages go.
06

How it works, step by step

  1. 1
    Declare exchanges and queues

    Durable, with bindings and DLX settings.

  2. 2
    Publish with a routing key

    For example notify.email.welcome.

  3. 3
    Exchange routes

    To every queue whose binding matches.

  4. 4
    Consumers receive with prefetch

    Limits in-flight messages per worker.

  5. 5
    Ack, nack, or reject

    Ack removes; nack requeues or dead-letters.

07

Exchange types

Routing key: notify.email.welcome

Step 1 / 5
Exchange typeBindingDelivered?
Directnotify.email.welcomeYes (exact match)
Topicnotify.email.*Yes (* matches one word)
Topicnotify.#Yes (# matches zero or more words)
Topicnotify.sms.*No
Fanout(ignored)Yes, to every bound queue

NOWExchange type: Direct | Binding: notify.email.welcome | Delivered?: Yes (exact match)

Topic exchanges give flexible routing without producers knowing which queues exist.

08

Implementation

import amqp from "amqplib"; const conn = await amqp.connect(process.env.AMQP_URL!);const ch = await conn.createChannel(); await ch.assertExchange("notify", "topic", { durable: true });await ch.assertExchange("notify.dlx", "fanout", { durable: true });await ch.assertQueue("email-jobs", { durable: true, arguments: { "x-queue-type": "quorum", "x-dead-letter-exchange": "notify.dlx" } });await ch.bindQueue("email-jobs", "notify", "notify.email.*"); // Publish (persistent)ch.publish("notify", "notify.email.welcome", Buffer.from(JSON.stringify({ userId: 42 })), { persistent: true }); // Consume with prefetch and explicit acksawait ch.prefetch(20);await ch.consume("email-jobs", async (msg) => {  if (!msg) return;  try {    await sendEmail(JSON.parse(msg.content.toString()));    ch.ack(msg);  } catch {    ch.nack(msg, false, false); // do not requeue: route to dead-letter exchange  }});
09

Complexity and performance

Throughput~10k-100k+ msg/s

Per cluster, depends on persistence.

LatencySub-millisecond to ms

Low for small messages.

10

Trade-offs

Routing flexibility vs raw throughput

RabbitMQ routes flexibly with per-message acks; Kafka offers higher throughput and replay but simpler routing.

Queues as buffers

Very long queues consume memory and slow the broker; RabbitMQ prefers queues that are consumed promptly.

11

Variants and related techniques

Streams

RabbitMQ Streams add Kafka-like append-only logs with replay.

Priority and delayed messages

Priority queues and a delayed-message plugin.

12

Common mistakes

  • Auto-ack mode.

    Fix: Messages are lost if the consumer crashes; use manual acks.

  • Unlimited prefetch.

    Fix: One consumer grabs everything; set prefetch.

  • Requeueing poison messages forever.

    Fix: Dead-letter after a retry limit.

13

Interview questions

When would you choose RabbitMQ over Kafka?

For task queues needing flexible routing, per-message acknowledgments, priorities, delays, or request-reply, at moderate throughput. Choose Kafka for high-volume event streams with multiple consumers and replay.

What does prefetch do?

It limits the number of unacknowledged messages delivered to a consumer, so work is distributed evenly and a slow consumer does not hoard messages.

14

Practice problems

ProblemDifficultyWhat it trains
Design routing for email, SMS, and push notificationsEasyTopic exchanges.
Add retries with delays and a DLQMediumDLX and TTL.