Home/Learn/RabbitMQ/Headers Exchange

Headers Exchange

Intermediate
Exchanges

Routes 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.

Java — headers exchange with whereAll/whereAny
@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.

Java — publishing messages with AMQP headers
@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.

Conceptual — topic vs headers exchange decision guide
// 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 needed

Key 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 Aria
1

How does a headers exchange differ from a topic exchange?

MediumAmazon
2

What is the difference between x-match=all and x-match=any?

EasyPivotal
3

When would you choose a headers exchange over a topic exchange?

HardNetflix
4

Is the routing key used by a headers exchange?

EasyInfosys
5

What is the performance trade-off of using a headers exchange?

MediumRevolut

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.

Loading discussion…