RabbitMQ
Spring Boot
Dynamic Queues
Queue Management
Programming

How to create dynamic queues in rabbit mq using spring boot?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Dynamic queues are useful when queue names are not known at startup, such as per-tenant jobs, temporary reply queues, or customer-specific routing. In Spring Boot, you normally create them programmatically with AmqpAdmin or RabbitAdmin instead of declaring every queue as a fixed bean.

When Dynamic Queues Make Sense

A static queue bean works well for long-lived application channels, but it becomes awkward when the queue name depends on runtime data. Examples include a queue per import job, one queue per account, or short-lived reply queues for a workflow engine.

The key design decision is that the broker objects still need to be declared explicitly, just later and with runtime values.

Spring Boot Setup

Add the AMQP starter so Spring Boot can create the connection factory and Rabbit components:

xml
1<dependency>
2  <groupId>org.springframework.boot</groupId>
3  <artifactId>spring-boot-starter-amqp</artifactId>
4</dependency>

Then configure the broker connection:

properties
1spring.rabbitmq.host=localhost
2spring.rabbitmq.port=5672
3spring.rabbitmq.username=guest
4spring.rabbitmq.password=guest

Spring Boot will automatically expose a RabbitTemplate and a RabbitAdmin bean if AMQP support is enabled.

Declaring a Queue at Runtime

The simplest approach is to inject AmqpAdmin and call declareQueue. You can also declare an exchange and binding in the same service method.

java
1package com.example.demo;
2
3import java.util.Map;
4import org.springframework.amqp.core.AmqpAdmin;
5import org.springframework.amqp.core.Binding;
6import org.springframework.amqp.core.BindingBuilder;
7import org.springframework.amqp.core.DirectExchange;
8import org.springframework.amqp.core.Queue;
9import org.springframework.stereotype.Service;
10
11@Service
12public class DynamicQueueService {
13
14    private final AmqpAdmin amqpAdmin;
15    private final DirectExchange exchange = new DirectExchange("jobs.exchange");
16
17    public DynamicQueueService(AmqpAdmin amqpAdmin) {
18        this.amqpAdmin = amqpAdmin;
19        this.amqpAdmin.declareExchange(exchange);
20    }
21
22    public String createQueueForTenant(String tenantId) {
23        String queueName = "jobs." + tenantId;
24        Queue queue = new Queue(queueName, true, false, false, Map.of());
25        Binding binding = BindingBuilder.bind(queue).to(exchange).with(queueName);
26
27        amqpAdmin.declareQueue(queue);
28        amqpAdmin.declareBinding(binding);
29        return queueName;
30    }
31}

This code creates a durable queue named from runtime input and binds it to a direct exchange using the same routing key.

Sending Messages to the Dynamic Queue

After the queue exists, publishing is the same as with any other RabbitMQ destination.

java
1package com.example.demo;
2
3import org.springframework.amqp.rabbit.core.RabbitTemplate;
4import org.springframework.stereotype.Service;
5
6@Service
7public class JobPublisher {
8
9    private final RabbitTemplate rabbitTemplate;
10
11    public JobPublisher(RabbitTemplate rabbitTemplate) {
12        this.rabbitTemplate = rabbitTemplate;
13    }
14
15    public void publishJob(String tenantId, String payload) {
16        String routingKey = "jobs." + tenantId;
17        rabbitTemplate.convertAndSend("jobs.exchange", routingKey, payload);
18    }
19}

The important part is that queue declaration and publishing agree on the same naming convention.

Listening to Dynamic Queues

Dynamic consumption is trickier than creation. @RabbitListener is great for known queues, but it is not ideal when queue names appear after startup. In those cases, use a listener container factory and register containers programmatically.

java
1package com.example.demo;
2
3import org.springframework.amqp.rabbit.connection.ConnectionFactory;
4import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
5import org.springframework.stereotype.Component;
6
7@Component
8public class DynamicListenerRegistrar {
9
10    private final ConnectionFactory connectionFactory;
11
12    public DynamicListenerRegistrar(ConnectionFactory connectionFactory) {
13        this.connectionFactory = connectionFactory;
14    }
15
16    public SimpleMessageListenerContainer startListener(String queueName) {
17        SimpleMessageListenerContainer container =
18            new SimpleMessageListenerContainer(connectionFactory);
19        container.setQueueNames(queueName);
20        container.setMessageListener(message ->
21            System.out.println("Received: " + new String(message.getBody())));
22        container.start();
23        return container;
24    }
25}

This lets you attach consumers after a queue has been created.

Common Pitfalls

The biggest mistake is creating queues with names derived from unchecked user input. Queue names should come from a safe naming rule, or you will make debugging and operations harder.

Another issue is forgetting bindings. Declaring the queue alone does not make published messages arrive unless the exchange and routing key match your send path.

Teams also underestimate lifecycle concerns. If queues are temporary, mark them with properties such as auto-delete or add expiration arguments. Otherwise, dynamic queues can pile up indefinitely.

Finally, @RabbitListener does not automatically become dynamic just because you use placeholders. If the queue truly appears at runtime, use a programmatic listener container.

Summary

  • In Spring Boot, dynamic queues are usually created with AmqpAdmin or RabbitAdmin.
  • Runtime declaration works best when queue names follow a clear naming convention.
  • Declaring the queue is only part of the job; exchange and binding setup must match the publisher.
  • Dynamic consumers often require programmatic listener containers instead of fixed @RabbitListener methods.
  • Plan queue lifecycle rules early so temporary queues do not accumulate forever.

Course illustration
Course illustration

All Rights Reserved.