On this page
Exchanges and Queues
RabbitMQ routing is defined by exchange type, bindings, and queue properties. Understanding these is essential for designing reliable messaging topologies.
Direct Exchange
Routes messages to queues whose binding key exactly matches the routing key.
channel.exchangeDeclare("orders.direct", BuiltinExchangeType.DIRECT, true);
channel.queueDeclare("orders.created", true, false, false, null);
channel.queueDeclare("orders.shipped", true, false, false, null);
channel.queueBind("orders.created", "orders.direct", "order.created");
channel.queueBind("orders.shipped", "orders.direct", "order.shipped");
channel.basicPublish("orders.direct", "order.created", null, message.getBytes());
Fanout Exchange
Broadcasts to all bound queues, ignoring routing keys.
channel.exchangeDeclare("notifications.fanout", BuiltinExchangeType.FANOUT, true);
channel.queueBind("email.queue", "notifications.fanout", "");
channel.queueBind("sms.queue", "notifications.fanout", "");
channel.queueBind("push.queue", "notifications.fanout", "");
// All three queues receive the message
channel.basicPublish("notifications.fanout", "", null, message.getBytes());
Topic Exchange
Routes based on wildcard pattern matching.
Routing key pattern:
* — matches exactly one word
# — matches zero or more words
Binding key "order.*" matches "order.created", "order.shipped"
Binding key "order.#" matches "order.created", "order.us.created"
Binding key "#.error" matches "payment.error", "order.us.error"
channel.exchangeDeclare("events.topic", BuiltinExchangeType.TOPIC, true);
channel.queueBind("us.orders", "events.topic", "order.us.*");
channel.queueBind("all.errors", "events.topic", "*.error");
channel.queueBind("everything", "events.topic", "#");
Queue Properties
Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", 60000); // message TTL: 60s
args.put("x-max-length", 10000); // max queue size
args.put("x-dead-letter-exchange", "dlx"); // dead letter exchange
args.put("x-dead-letter-routing-key", "failed");
channel.queueDeclare("orders.queue", true, false, false, args);
| Property | Description |
|---|---|
durable |
Survive broker restart |
exclusive |
Only this connection can use |
autoDelete |
Delete when no consumers |
x-message-ttl |
Message expiration |
x-max-length |
Max messages in queue |
Dead Letter Exchange (DLX)
Handle failed or expired messages:
// Main queue with DLX
Map<String, Object> args = Map.of(
"x-dead-letter-exchange", "orders.dlx",
"x-dead-letter-routing-key", "order.failed"
);
channel.queueDeclare("orders.queue", true, false, false, args);
channel.queueDeclare("orders.failed", true, false, false, null);
channel.queueBind("orders.failed", "orders.dlx", "order.failed");
Spring Configuration
@Configuration
public class RabbitConfig {
@Bean
public TopicExchange ordersExchange() {
return new TopicExchange("orders.topic", true, false);
}
@Bean
public Queue ordersCreatedQueue() {
return QueueBuilder.durable("orders.created")
.withArgument("x-dead-letter-exchange", "orders.dlx")
.build();
}
@Bean
public Binding binding(Queue ordersCreatedQueue, TopicExchange ordersExchange) {
return BindingBuilder.bind(ordersCreatedQueue)
.to(ordersExchange).with("order.created");
}
}
Best Practices
- Use topic exchanges for flexible routing in event-driven systems
- Always configure dead letter exchanges for production queues
- Set message TTL to prevent stale messages accumulating
- Use durable exchanges and queues unless ephemeral data is intended
- Design queue names to reflect their purpose (
orders.created,payments.failed)