Home/Learn/RabbitMQ/Topic Exchange

Topic Exchange

Intermediate
Exchanges

Routes by pattern-matching the routing key using * (one word) and # (zero or more words); enables flexible multi-level routing such as logs.error.# or payments.*.

Overview

The topic exchange is the most flexible exchange type in RabbitMQ. It routes messages by matching the message's routing key (a dot-delimited string, e.g., order.payment.failed) against binding patterns on queues. Two wildcards power the pattern matching: `*` matches exactly one word (one dot-delimited segment), and `#` matches zero or more words. This makes it the go-to choice for complex routing scenarios — for example, a log aggregation system where different queues receive error-only logs, payment-specific events, or all events from a given service. A single topic exchange can replace a combination of direct and fanout exchanges for most real-world routing needs.

Wildcard Patterns — * and #

Routing keys for topic exchanges are dot-delimited strings (e.g., `order.payment.failed`). Binding patterns use:

`*` — matches exactly one word: `order.*` matches `order.created` and `order.cancelled` but NOT `order.payment.failed` (two words after dot).

`#` — matches zero or more words: `order.#` matches `order`, `order.created`, and `order.payment.failed`. `#` alone matches every routing key (behaves like fanout).

A queue can have multiple bindings on a topic exchange, receiving messages that match any of its patterns (OR semantics).

RabbitMQ — Topic Routing Key Patterns
# Routing key structure:  <domain>.<entity>.<event>
# Examples:
#   order.payment.succeeded
#   order.payment.failed
#   order.shipment.dispatched
#   notification.email.sent
#   audit.*.created

# Binding patterns and what they match:
# order.#              → all order events (payment, shipment, etc.)
# order.payment.*      → order.payment.succeeded, order.payment.failed
# *.payment.*          → anything with "payment" in the middle
# #.failed             → any event ending in "failed" from any domain
# #                    → every message (fanout behaviour)

Declaring a Topic Exchange — Low-Level Java

Declare the exchange as type `topic`, then bind queues with their respective patterns. A queue can have multiple bindings; messages matching any binding are delivered to that queue.

Java — AMQP Client
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

// Declare a durable topic exchange
channel.exchangeDeclare("events", BuiltinExchangeType.TOPIC, true);

// Declare queues
channel.queueDeclare("payment-events-queue", true, false, false, null);
channel.queueDeclare("all-order-events-queue", true, false, false, null);
channel.queueDeclare("failed-events-queue", true, false, false, null);

// Bind queues with patterns
channel.queueBind("payment-events-queue",   "events", "order.payment.*");
channel.queueBind("all-order-events-queue", "events", "order.#");
channel.queueBind("failed-events-queue",    "events", "#.failed");

// Publish a message — the routing key determines which queues receive it
String routingKey = "order.payment.failed";
channel.basicPublish("events", routingKey, null, payload.getBytes());
// → delivered to: payment-events-queue (order.payment.*  ✓)
// → delivered to: all-order-events-queue  (order.#  ✓)
// → delivered to: failed-events-queue     (#.failed ✓)

Spring AMQP — TopicExchange Configuration

Spring AMQP provides clean builder-style beans for exchanges, queues, and bindings. Declare a TopicExchange, Queues, and BindingBuilder.bind(...).to(exchange).with(pattern).

Java — Spring AMQP TopicExchange
@Configuration
public class MessagingConfig {

    @Bean
    public TopicExchange eventsExchange() {
        return new TopicExchange("events", true, false);
    }

    @Bean
    public Queue paymentEventsQueue() {
        return QueueBuilder.durable("payment-events-queue").build();
    }

    @Bean
    public Queue allOrderEventsQueue() {
        return QueueBuilder.durable("all-order-events-queue").build();
    }

    @Bean
    public Binding paymentBinding(Queue paymentEventsQueue, TopicExchange eventsExchange) {
        return BindingBuilder.bind(paymentEventsQueue)
            .to(eventsExchange)
            .with("order.payment.*");
    }

    @Bean
    public Binding allOrderBinding(Queue allOrderEventsQueue, TopicExchange eventsExchange) {
        return BindingBuilder.bind(allOrderEventsQueue)
            .to(eventsExchange)
            .with("order.#");
    }
}

// Publisher
@Service
@RequiredArgsConstructor
public class EventPublisher {
    private final RabbitTemplate rabbitTemplate;

    public void publishPaymentFailed(String orderId) {
        rabbitTemplate.convertAndSend(
            "events",
            "order.payment.failed",   // routing key
            new PaymentFailedEvent(orderId)
        );
    }
}

Key Points to Remember

  • 1`*` matches exactly one word; `#` matches zero or more words in a dot-delimited routing key.
  • 2A single routing key can match multiple queue bindings simultaneously — messages are delivered to all matching queues.
  • 3Binding pattern `#` alone turns a topic exchange into a fanout — use sparingly.
  • 4Topic exchanges combine the flexibility of routing keys with pattern-based subscription — one exchange can serve many consumer use cases.
  • 5In Spring AMQP, use BindingBuilder.bind(queue).to(topicExchange).with("pattern") for each binding.
  • 6Design routing key namespaces upfront: domain.entity.event (e.g., order.payment.failed) scales well to new event types.

Interview Questions

Sign in to ask Aria
1

What is the difference between * and # wildcards in a RabbitMQ topic exchange?

EasyAmazon
2

How is a topic exchange different from a direct exchange?

EasyFlipkart
3

A message with routing key "order.payment.failed" is published. Which queues with bindings "order.#", "*.payment.*", and "order.created" receive it?

MediumUber
4

How would you design a routing key namespace for a multi-service event bus?

HardNetflix
5

Can one queue have multiple bindings on a topic exchange? What are the semantics?

MediumGoogle

Ask Aria about Topic Exchange

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…