Lesson 5 / 25
Topic and Headers Exchanges
Use topic wildcards and header matching for flexible routing.
Pattern-based routing
A topic exchange routes by matching the routing key against binding patterns. Routing keys are words separated by dots, such as order.placed.in or payment.failed.card. In binding patterns, * matches exactly one word and # matches zero or more words. So order.*.in matches order.placed.in but not order.placed; order.# matches everything starting with order; and # alone matches every message, behaving like fanout. Topic exchanges are the most common choice for event routing: producers publish descriptive keys, and each consumer binds the patterns it cares about. A headers exchange ignores the routing key and matches on message header values, with x-match set to all (every listed header must match) or any (at least one). Headers exchanges are useful when routing depends on several attributes, but topic exchanges are simpler and more widely used.
Topic bindings for an orders exchange
Each consumer chooses the subset of events it needs.
channel.exchange_declare("orders", exchange_type="topic", durable=True)
bindings = {
"billing.orders": ["order.placed.*", "order.cancelled.*"],
"india-ops.orders": ["order.*.in"], # all Indian order events
"audit.orders": ["order.#"], # everything about orders
}
for queue, patterns in bindings.items():
channel.queue_declare(queue, durable=True, arguments={"x-queue-type": "quorum"})
for p in patterns:
channel.queue_bind(queue, "orders", routing_key=p)
channel.basic_publish("orders", "order.placed.in", body=b'{"orderId": "o-1001"}')
# delivered to billing.orders, india-ops.orders and audit.ordersMail sorting by postcode
A topic pattern is like a sorter that says "anything starting with 400 goes to Mumbai" (400.#) or "any single-digit district in 560" (560.*). Senders write full addresses; sorters decide the coverage.
Quick check: Which routing key matches the binding pattern `order.*.in`?
- order.placed
- order.placed.in
- order.placed.express.in
- payment.placed.in
Answer
order.placed.in — `*` matches exactly one word, so only `order.placed.in` fits.