RabbitMQ Exchange Types

Fatiha Beqirovski
Trendyol Tech
Published in
6 min readMay 28, 2020

Before we start with this blog, I expect you to have a good understanding on what RabbitMQ is, what it’s used for, what exchange, queue, binding and routing keys are. This post is focused on exchange types only.

RabbitMQ has four different types of exchanges; Direct, Topic, Fanout, Headers. Each exchange type routes the message differently using different parameters and bindings setups. Clients can either create own exchanges or use the predefined default exchanges. Exchange can have bound queues or exchanges.

The exchange-exchange binding allows for messages to be sent/routed from one exchange to another exchange. Exchange-exchange binding works more or less the same way as exchange-to-queue binding. The only noteworthy difference from the surface is that both exchanges; source and destination have to be specified. The examples in this blog will be given using exchange-queue binding.

Standard RabbitMQ message flow

The simple cycle of RabbitMQ message is as follows:

  • The producer publishes a message to exchange.
  • After receiving the message, the exchange is responsible for forwarding it. The exchange routes the message to the queues, exchanges bound to it.
  • Queue receives the message and keeps it until the consumer consumes it.
  • Lastly, the consumer handles the message.

Now, let’s see how this cycle differs in different RabbitMQ exchange types.

1. Direct Exchange

Direct Exchange message flow

The routing in direct exchange is simple — a message goes to the queues whose binding key exactly matches the routing key of the message.

The direct exchange type is useful to distinguish messages published to the same exchange using a simple string identifier.

Let’s imagine we have a direct exchange OrderCreatedEvents_Direct and two queues bound to it.

order_create_queue is bound with binding key order-create and order_create_log_queue is bound with order-create-log routing key.

When a new message with routing key order-create arrives at the direct exchange, the exchange routes it to the queue with the appropriate routing key, in this case to queue order_create_queue.

If the message routing key does not match any binding key, the message is discarded. If more than one queue is bound to exchange with same binding key, the direct exchange will broadcast the message to all matching queues.

2. Topic Exchange

Topic Exchange message flow

Topic exchange is similar to direct exchange, but the routing is done according to the routing pattern. Instead of using fixed routing key, it uses wildcards. Messages are routed to one or many queues based on a matching between a message routing key and pattern. The routing key must consist of list of words delimited by a period “.”.

For example, let’s suppose we have following routing patterns.

  • order.logs.customer
  • order.logs.international
  • order.logs.personnel
  • order.logs.customer.electronics
  • order.logs.personnel.electronics
  • order.logs.international.electronics

The routing patterns may also contain an asterisk (“*”) to match a word in a specific position of the routing key. For example, a routing pattern of “order.*.*.electronics” only match routing keys where the first word is “order” and the fourth word is “electronics”.

The routing pattern may also contain a pound symbol (“#”) which means a match of zero or more words. For example, a routing pattern of “order.logs.customer.#” matches any routing keys beginning with “order.logs.customer “.

The consumers specify which topics they are interested in and would like to receive messages from. The consumer creates a queue and sets up a binding with a given routing pattern to the exchange. All messages with a routing key that match the routing pattern are routed to the queue and stay there until the consumer handles the message.

Let’s look at an example.

Suppose we have a topic exchange with three queues bound to it.

customer_orders_queue: wants to receive all customer order logs. It is bound to topic exchange using routing pattern order.logs.customer.#

all_order_logs_queue: wants to receive all order logs. It is bound to topic exchange using routing pattern order.logs.#

electronics_order_logs_queue: want to receive all electronics order logs. It is bound to topic exchange using routing pattern order.logs.*.electronics

When we publish a message with routing pattern order.logs.customer.electronics all the bound queues will receive it.

3. Fanout Exchange

Fanout Exchange message flow

A fanout exchange copies and routes a received message to all queues that are bound to it regardless of routing keys or patterns. The keys provided will simply be ignored.

Fanout exchanges can be useful when the same message needs to be sent to one or more queues with consumers who may process the same message in different ways.

For example, when an order is created, the warehouse needs to be notified so it can prepare the order, also the cargo company needs to be notified, a consumer wishing to keep logs of orders also needs to be notified.

Let’s suppose we have a fanout exchange having three queues bound to it with routing keys.

A message is sent to exchange OrderCreatedEvents_Fanout. The message is routed to all queues warehouse_queue, cargo_queue, logs_queue because all queues are bound to the exchange. Routing keys, if any will be ignored.

4. Headers Exchange

Headers Exchange message flow

A headers exchange routes messages based on arguments containing headers and optional values. It uses the message header attributes for routing.

A special argument named “x-match”, added in the binding between exchange and queue, specifies if all headers must match or just one. The “x-match” property can have two different values: “any” or “all”,where “all” is the default value. A value of “all” means all header pairs (key, value) must match, while value of “any” means at least one of the header pairs must match.

Let’s create a headers exchange OrderCreatedEvents_Header and bind three queues to it.

Q1 with arguments (key = value): format = pdf, type = report, x-match = all

Q2 with arguments (key = value): format = pdf, type = log, x-match = any

Q3 with arguments (key = value): format = zip, type = report, x-match = all

When the message is published to the exchange with header arguments (key = value): “format = pdf”, “type = report”, and with the binding argument “x-match = all” it will be delivered to Q1.

When the message is published to the exchange with header arguments of (key = value): “format = pdf” and with the binding argument “x-match = any” it will be delivered to Q2 since it satisfy one condition and does not have to satisfy all conditions.

There are two more exchange types.

Default Exchange

The default exchange is a pre-declared direct exchange that has no name. It is usually referred by an empty string. If you use default exchange your message is delivered to the queue with a name equal to the routing key of the message. Every queue is automatically bound to the default exchange with a routing key which is the same as the queue name.

Dead Letter Exchange

If there is no matching queue for the message, the message is dropped. RabbitMQ provides an AMQP extension known as the “Dead Letter Exchange”. This exchange which provides the functionality to capture messages that are not deliverable.

Thank you for reading! 😻

--

--