RabbitMQ Topic Exchange
The topic exchange is the most flexible exchange type in RabbitMQ. It routes messages based on wildcard pattern matching against the routing key. Instead of requiring an exact match like a direct exchange, or ignoring the key entirely like a fanout exchange, the topic exchange lets queues subscribe to categories of messages using patterns.
The Newspaper Subscription Analogy
A newspaper publisher offers sections: Sports, Finance, Technology, Local, International. Readers can subscribe to exactly the sections they want. One reader subscribes to all Sports articles. Another subscribes to all International Finance stories. A third wants everything. The topic exchange works the same way — queues subscribe to patterns, and messages are delivered only to matching queues.
Routing Key Format
Topic exchange routing keys are dot-separated words. For example:
order.placed.usapayment.failed.europelog.error.databasesensor.temperature.building1
Each word segment represents a category level. The exchange uses these segments to match binding patterns.
Wildcard Characters
Topic exchange binding patterns support two wildcards:
*(asterisk) — matches exactly one word in that position#(hash) — matches zero or more words
Pattern Matches Does NOT Match
-----------------------------------------------------------------
order.* order.placed order.placed.usa
order.cancelled order
order.# order.placed payment.placed
order.placed.usa
order
*.error.* log.error.db error.db
app.error.network log.error
# everything (catch-all) (nothing)
log.# log app.log
log.error
log.error.database
Topic Exchange Routing Diagram
[Topic Exchange: "app-events"] | +-- binding: "order.#" --> [order-team-queue] | +-- binding: "*.error.*" --> [error-alert-queue] | +-- binding: "payment.*" --> [payment-queue] | +-- binding: "#" --> [audit-log-queue] Message: routing_key = "order.placed.usa" --> order-team-queue ✓ (matches "order.#") --> audit-log-queue ✓ (matches "#") --> error-alert-queue ✗ (does not match "*.error.*") --> payment-queue ✗ (does not match "payment.*") Message: routing_key = "payment.failed" --> payment-queue ✓ (matches "payment.*") --> audit-log-queue ✓ (matches "#") --> order-team-queue ✗ (does not match "order.#") --> error-alert-queue ✗ (does not match "*.error.*")
Topic Exchange as Direct Exchange
If you use no wildcards in your binding patterns, a topic exchange behaves exactly like a direct exchange. A pattern of payment.success only matches a routing key of exactly payment.success.
Topic Exchange as Fanout Exchange
If you use # as the only binding pattern, the queue receives every message regardless of routing key. This replicates fanout behaviour.
Real-World Use Case: IoT Sensor Network
A factory has hundreds of sensors. Each sensor publishes messages with routing keys in this format:
<building>.<floor>.<sensor-type>
Examples: buildingA.floor3.temperature, buildingB.floor1.humidity
[Topic Exchange: "factory-sensors"]
|
+-- "buildingA.#" --> [building-a-team-queue]
| (all sensors in building A)
|
+-- "*.*.temperature" --> [temp-monitor-queue]
| (all temperature sensors everywhere)
|
+-- "buildingB.floor1.*" --> [floor1b-queue]
| (all sensors on floor 1 of building B)
|
+-- "#" --> [central-log-queue]
(everything)
A message from buildingA.floor2.temperature goes to building-a-team-queue, temp-monitor-queue, and central-log-queue.
Setting Up a Topic Exchange
In Python using pika:
# Declare exchange
channel.exchange_declare(exchange='app-events', exchange_type='topic')
# Declare queue and bind with pattern
channel.queue_declare(queue='order-queue', durable=True)
channel.queue_bind(
exchange='app-events',
queue='order-queue',
routing_key='order.#'
)
# Producer publishes
channel.basic_publish(
exchange='app-events',
routing_key='order.placed.eu',
body='{"order_id": 9901}'
)
Choosing Between Direct, Fanout, and Topic
Need exact routing? --> Direct Exchange Need to broadcast all? --> Fanout Exchange Need pattern-based routing? --> Topic Exchange
In practice, topic exchanges cover the widest range of real-world scenarios. Most production systems with multiple event types use a topic exchange as their main routing hub.
Summary
The topic exchange routes messages using dot-separated routing keys matched against wildcard binding patterns. The * wildcard matches one word. The # wildcard matches zero or more words. Topic exchanges combine the precision of direct exchanges with the flexibility of fanout exchanges. They are the best choice when your messaging system has multiple event categories that different consumers need to subscribe to selectively.
