# RabbitMQ — Part 1: Exchanges, Queues, and Routing

## 1. What RabbitMQ Is

RabbitMQ is a **message broker** implementing (primarily) the **AMQP 0-9-1** protocol (Advanced Message Queuing Protocol). It is the classic "smart broker, dumb consumer" design: RabbitMQ itself decides exactly which queue(s) a message ends up in based on routing rules you configure, and a consumer just connects to a queue and receives whatever arrives. This is a fundamentally different philosophy from Kafka (covered in the next topic), where the broker is closer to "dumb storage" and consumers do the work of deciding what to read.

## 2. The Three AMQP Building Blocks

RabbitMQ's model has three core pieces, and understanding how they connect is the entire key to using RabbitMQ correctly.

| Piece | Role |
|---|---|
| **Exchange** | Receives messages from producers and decides which queue(s), if any, to route each message to. Producers never publish directly to a queue — they always publish to an exchange. |
| **Queue** | An ordered buffer that holds messages until a consumer receives and acknowledges them. Consumers attach to queues, never to exchanges. |
| **Binding** | A rule connecting an exchange to a queue, usually with a **routing key** pattern, telling the exchange "route matching messages to this queue." |

```
Producer --publish--> [ Exchange ] --(binding rules)--> [ Queue A ] --> Consumer 1
                                    --(binding rules)--> [ Queue B ] --> Consumer 2
```

A message published to an exchange with no matching binding is, by default, simply dropped (unless the publisher opts into "mandatory" delivery and handles the returned message).

## 3. Exchange Types

The exchange type determines the matching algorithm used to decide which bound queues receive a given message.

| Exchange type | Routing behavior |
|---|---|
| **Direct** | Delivers to any queue whose binding key exactly equals the message's routing key. Used for precise, single-destination routing (e.g. routing key `payments.failed` goes only to the queue bound with exactly `payments.failed`). |
| **Fanout** | Ignores the routing key entirely and delivers to *every* queue bound to the exchange. Used for broadcast — every subscriber gets every message. |
| **Topic** | Matches the routing key against binding patterns using wildcards: `*` matches exactly one word, `#` matches zero or more words (words are separated by `.`). Used for flexible, hierarchical routing (e.g. a binding of `orders.*.created` matches `orders.eu.created` and `orders.us.created` but not `orders.eu.region.created`). |
| **Headers** | Matches on message header key/value pairs instead of the routing key. Rare in practice; topic exchanges cover most of the same use cases more simply. |

```
Topic exchange example — routing key "orders.eu.created" published:

  binding "orders.*.created"   -> MATCH (one wildcard word: "eu")
  binding "orders.#"           -> MATCH (# covers any remaining words)
  binding "orders.us.created"  -> NO MATCH (exact segment differs)
  binding "orders.eu.cancelled"-> NO MATCH (last segment differs)
```

![A topic exchange matching one routing key against multiple bindings, delivering the message to every queue whose pattern matches](diagrams/01-exchange-routing.svg)

## 4. A Concrete Routing Walkthrough

Imagine an order-processing system publishing events to a topic exchange named `orders`, with routing keys shaped like `orders.<region>.<event>`.

```
Bindings:
  queue "eu-orders"        <- binding key "orders.eu.#"
  queue "all-created"      <- binding key "orders.*.created"
  queue "audit-log"        <- binding key "orders.#"
```

A message published with routing key `orders.eu.created` matches all three bindings — it lands in `eu-orders`, `all-created`, AND `audit-log`. A message with routing key `orders.us.cancelled` matches only `audit-log` (`orders.#` covers everything).

This is the mechanism that gives RabbitMQ its flexibility: one producer, one exchange, and any number of independently-evolving consumer teams each defining their own queue and binding pattern without touching the producer or each other.

## 5. Queues: Durable, Exclusive, and Auto-Delete

Queues have properties set at creation time that control their lifecycle:

- **Durable** — the queue definition survives a broker restart (messages inside still need to be individually marked persistent to survive too — durability of the queue and persistence of its messages are separate settings).
- **Exclusive** — only the connection that created the queue can use it; deleted automatically when that connection closes. Common for temporary, per-client reply queues.
- **Auto-delete** — the queue is deleted once its last consumer disconnects.

A typical durable work queue for background jobs is created durable, non-exclusive, non-auto-delete, so it survives broker restarts and keeps accepting messages even with zero consumers connected.

## 6. Basic Consumption and Acknowledgement

A consumer subscribes to a queue and receives messages one at a time (or in a prefetched batch — see Part 2). After successfully processing a message, it sends an **ack** back to RabbitMQ, which then permanently removes that message from the queue. If the consumer disconnects (or explicitly **nacks**) before acking, RabbitMQ **redelivers** the message — to the same consumer on reconnect, or to another consumer in the pool.

```
Consumer receives message  -> processes it  -> ack()  -> RabbitMQ deletes it from the queue
Consumer crashes before ack -> RabbitMQ detects the dead connection -> requeues the message
                                                                        for another consumer
```

This ack-then-delete model is the core reason RabbitMQ queues behave like a true work queue: once a message is acked, it is gone, full stop — there is no "replay from the beginning" the way there is with Kafka's log.

Continue to `broker_rabbitmq_theory_2.md` for prefetch, clustering, quorum queues, and the real storage model under the hood.
