Implementing Delayed Message Delivery in RabbitMQ with the Delayed Message Plugin
Plugin Installattion
Download the rabbitmq_delayed_message_exchange plugin archive from the official repository. For this guide, version 3.10.0 is used. Transfer the .ez file to the RabbitMQ server and place it inside the plugins directory of your RabbitMQ installation:
scp rabbitmq_delayed_message_exchange-3.10.0.ez root@10.211.55.4:/usr/local/software/mv rabbitmq_delayed_message_exchange-3.10.0.ez /usr/local/software/rabbitmq_server-3.10.0/plugins
Enable the plugin and restart the broker:
rabbitmq-plugins enable rabbitmq_delayed_message_exchangerabbitmq-server start
After the restart, the plugin adds a new exchange type x-delayed-message that supports holding messages for a configured amount of time before routing them to the target queue.
Configuration with Spring AMQP
A dedicated configuration class registers the needed exchange, queue, and binding. The exchange is set up as a CustomExchange with the type x-delayed-message and an extra argument that defines the underlying routing behaviour (x-delayed-type).
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DelayedExchangeSetup {
public static final String ORDER_DELAYED_QUEUE = "orders.delayed.queue";
public static final String ORDER_DELAYED_EXCHANGE = "orders.delayed.exchange";
public static final String ORDER_DELAYED_ROUTING = "orders.delayed.key";
@Bean
public CustomExchange delayedOrderExchange() {
Map<String, Object> args = new HashMap<>();
args.put("x-delayed-type", "direct");
return new CustomExchange(ORDER_DELAYED_EXCHANGE,
"x-delayed-message",
true,
false,
args);
}
@Bean
public Queue delayedOrderQueue() {
return new Queue(ORDER_DELAYED_QUEUE);
}
@Bean
public Binding delayedOrderBinding() {
return BindingBuilder
.bind(delayedOrderQueue())
.to(delayedOrderExchange())
.with(ORDER_DELAYED_ROUTING)
.noargs();
}
}
Sending Delayed Messages
The producer uses RabbitTemplate and sets the delay (in milliseconds) through the MessagePostProcessor interface.
@RestController
public class OrderController {
private final RabbitTemplate rabbitTemplate;
public OrderController(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
@GetMapping("/orders/delayed/{payload}/{delay}")
public void createDelayedOrder(@PathVariable String payload,
@PathVariable int delay) {
rabbitTemplate.convertAndSend(
DelayedExchangeSetup.ORDER_DELAYED_EXCHANGE,
DelayedExchangeSetup.ORDER_DELAYED_ROUTING,
payload,
message -> {
message.getMessageProperties().setDelay(delay);
return message;
});
}
}
Handling Delayed Messages
On the consumer side, a listener is attached to the delayed queue. It receives the message only after the specified delay has elapsed.
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class DelayedOrderProcessor {
@RabbitListener(queues = DelayedExchangeSetup.ORDER_DELAYED_QUEUE)
public void process(Message msg) {
String order = new String(msg.getBody());
System.out.println("Processing delayed order: " + order);
}
}
The delayed message plugin ensures that messages are routed strictly according to their individual delay settings, avoidnig the ordering pitfalls sometimes observed with dead‑letter‑based aprpoaches.