Direct Exchange
BeginnerRoutes messages to queues whose binding key exactly matches the message's routing key; ideal for simple unicast routing such as task dispatch.
Overview
A direct exchange routes each message to exactly the queues whose binding key matches the message's routing key (exact string match). It is the simplest and most efficient exchange type. The default exchange in RabbitMQ is a pre-declared direct exchange with no name — publishing to it with a routing key equal to a queue name delivers directly to that queue, making it look like a direct queue-to-queue connection. Direct exchanges are ideal for task queues (worker pool pattern) where each message should be handled by exactly one worker.
Direct Exchange Routing
Bind multiple queues to the same direct exchange with different routing keys to route messages to different services. A queue can also be bound with multiple routing keys.
@Configuration
public class DirectExchangeConfig {
@Bean
public DirectExchange notificationExchange() {
return new DirectExchange("notifications");
}
// Email queue — bound with routing key "email"
@Bean public Queue emailQueue() {
return QueueBuilder.durable("notifications.email").build();
}
@Bean public Binding emailBinding(Queue emailQueue, DirectExchange exchange) {
return BindingBuilder.bind(emailQueue).to(exchange).with("email");
}
// SMS queue — bound with routing key "sms"
@Bean public Queue smsQueue() {
return QueueBuilder.durable("notifications.sms").build();
}
@Bean public Binding smsBinding(Queue smsQueue, DirectExchange exchange) {
return BindingBuilder.bind(smsQueue).to(exchange).with("sms");
}
}
// Producer — route to email or sms based on notification type
public void sendNotification(Notification n) {
rabbitTemplate.convertAndSend("notifications", n.getType().name().toLowerCase(), n);
// type=EMAIL → routing key "email" → notifications.email queue
// type=SMS → routing key "sms" → notifications.sms queue
}Default Exchange (Implicit Direct)
The default exchange is a nameless direct exchange. Publishing to the default exchange with routing key equal to a queue name delivers directly to that queue — no explicit binding needed.
// Default exchange — publish directly to a named queue
rabbitTemplate.convertAndSend(
"", // empty string = default exchange
"order-processor", // routing key = queue name
orderEvent
);
// This is equivalent to using the queue name as a direct address
// RabbitMQ automatically binds every queue to the default exchange
// with the queue name as the routing key
// Use cases for default exchange:
// ✓ Simple task queues where routing logic is trivial
// ✓ Quick prototyping — no exchange/binding setup needed
// ✓ When you always know the exact destination queue
// Spring AMQP convenience shortcut
rabbitTemplate.convertAndSend("order-processor", orderEvent);
// → uses default exchange internallyWorker Pool Pattern with Direct Exchange
Multiple consumers on the same queue share the work — RabbitMQ delivers each message to exactly one consumer (round-robin by default). Set prefetch count to prevent fast consumers from hoarding messages.
// Multiple workers share the same queue
@Component
public class OrderWorker {
@RabbitListener(
queues = "order-processor",
concurrency = "3-10" // 3 initial threads, scale up to 10
)
public void processOrder(OrderEvent event) {
// Each message processed by exactly ONE of the 3-10 worker threads
orderService.process(event);
}
}
// Prefetch — how many unacked messages each consumer holds at once
// Low prefetch = fairer distribution; high prefetch = better throughput
// application.properties
spring.rabbitmq.listener.simple.prefetch=5
// Without prefetch (default=250), a fast consumer drains the queue
// while slow consumers sit idle — bad for task queues
// For I/O bound tasks (DB, HTTP): prefetch=1-5
// For CPU light tasks: prefetch=10-50Key Points to Remember
- 1Direct exchange routes messages where routing key = binding key (exact match).
- 2The default exchange is a pre-declared direct exchange — routing key must equal the queue name.
- 3One exchange can route to multiple queues with different binding keys.
- 4Multiple consumers on the same queue receive messages in round-robin (competing consumers).
- 5Set prefetch (QoS) to limit unacked messages per consumer — prevents starvation of slow workers.
- 6Direct exchange is ideal for simple task dispatch, worker pools, and point-to-point routing.
Interview Questions
Sign in to ask AriaHow does a direct exchange route messages?
What is the RabbitMQ default exchange and how does it work?
How do you implement a worker pool (competing consumers) with RabbitMQ?
What is the difference between direct and topic exchange?
What is prefetch count and how does it affect worker pool fairness?
Ask Aria about Direct 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.