Headers Exchange
IntermediateRoutes based on AMQP message header attributes instead of routing keys; supports x-match=all (AND) or x-match=any (OR) semantics for complex attribute-based routing.
Overview
A headers exchange routes messages based on AMQP message header key-value pairs rather than the routing key. Bindings specify a set of required headers (and optional values). The x-match binding argument controls matching: x-match=all means ALL specified headers must match (AND semantics); x-match=any means at least ONE header must match (OR semantics). Headers exchanges are more expressive than topic exchanges for multi-attribute routing, but are slower and less common — most teams prefer topic exchanges for their simplicity.
Declaring a Headers Exchange
Bind queues with header attribute maps. The x-match argument (any|all) is required. Any header starting with x- is special in AMQP; use plain names for your application headers.
@Configuration
public class HeadersExchangeConfig {
@Bean
public HeadersExchange notificationExchange() {
return new HeadersExchange("notifications.headers");
}
// Queue 1: receives messages with format=pdf AND priority=high
@Bean public Queue pdfHighQueue() {
return QueueBuilder.durable("notifications.pdf.high").build();
}
@Bean public Binding pdfHighBinding(Queue pdfHighQueue,
HeadersExchange exchange) {
return BindingBuilder.bind(pdfHighQueue).to(exchange)
.whereAll("format", "priority") // AND semantics
.matches(Map.of("format", "pdf", "priority", "high"));
}
// Queue 2: receives messages with format=email OR format=sms (any)
@Bean public Queue emailOrSmsQueue() {
return QueueBuilder.durable("notifications.email-or-sms").build();
}
@Bean public Binding emailOrSmsBinding(Queue emailOrSmsQueue,
HeadersExchange exchange) {
return BindingBuilder.bind(emailOrSmsQueue).to(exchange)
.whereAny("format") // OR semantics
.matches(Map.of("format", "email")); // OR format=sms (separate binding)
}
}Publishing with Headers
Set headers on the MessageProperties before publishing. The exchange evaluates headers against all bindings and routes to matching queues.
@Service
public class NotificationPublisher {
private final RabbitTemplate rabbitTemplate;
public void sendPdfReport(ReportEvent event, boolean highPriority) {
rabbitTemplate.convertAndSend(
"notifications.headers",
"", // routing key is ignored by headers exchange
event,
msg -> {
MessageProperties props = msg.getMessageProperties();
props.setHeader("format", "pdf");
props.setHeader("priority", highPriority ? "high" : "normal");
props.setHeader("region", event.getRegion());
return msg;
}
);
}
public void sendEmail(EmailEvent event) {
rabbitTemplate.convertAndSend(
"notifications.headers", "", event,
msg -> {
msg.getMessageProperties().setHeader("format", "email");
return msg;
}
);
}
}Headers vs Topic Exchange — When to Use Which
Topic exchanges use a single routing key with wildcard patterns — simpler and faster. Headers exchanges support multi-dimensional routing criteria. Use headers when routing depends on multiple independent attributes that don't fit naturally into a dot-separated routing key.
// Topic exchange — routing key encodes attributes in a dot-separated string
// "notification.email.high" → email high-priority
// "notification.pdf.normal" → pdf normal-priority
// Works well when attributes are hierarchical and few
// Headers exchange — each attribute is a separate header
// format=pdf, priority=high, region=EU
// Advantage: cleaner separation of concerns, evolve attributes independently
// Disadvantage: slower routing, harder to monitor, less tool support
// Decision guide:
// ✓ Use TOPIC when:
// - Routing key is a natural hierarchy (e.g. log.error.payment)
// - Wildcard matching on prefixes/suffixes is needed
// - 1-2 routing dimensions
// ✓ Use HEADERS when:
// - 3+ independent routing dimensions
// - Attributes have no natural ordering
// - AND/OR combinations are required
// In practice: most teams use topic exchanges for 90% of use cases
// Headers exchanges are rarely neededKey Points to Remember
- 1Headers exchanges route based on message header key-value pairs, not the routing key.
- 2x-match=all (AND): all specified headers must match; x-match=any (OR): at least one must match.
- 3The routing key is ignored by headers exchanges — pass an empty string.
- 4Set headers via MessageProperties.setHeader() on the producer side.
- 5Headers exchanges are slower than direct/topic exchanges due to header evaluation overhead.
- 6Use headers exchanges for multi-dimensional routing; prefer topic exchanges for most use cases.
Interview Questions
Sign in to ask AriaHow does a headers exchange differ from a topic exchange?
What is the difference between x-match=all and x-match=any?
When would you choose a headers exchange over a topic exchange?
Is the routing key used by a headers exchange?
What is the performance trade-off of using a headers exchange?
Ask Aria about Headers 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.