Home/Learn/RabbitMQ/Direct Exchange

Direct Exchange

Beginner
Exchanges

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

Java — direct exchange with multiple bindings
@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.

Java — default exchange (queue-name routing)
// 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 internally

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

Java + Properties — worker pool with prefetch
// 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-50

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

How does a direct exchange route messages?

EasyInfosys
2

What is the RabbitMQ default exchange and how does it work?

EasyPivotal
3

How do you implement a worker pool (competing consumers) with RabbitMQ?

MediumAmazon
4

What is the difference between direct and topic exchange?

MediumWipro
5

What is prefetch count and how does it affect worker pool fairness?

MediumNetflix

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.

Loading discussion…