Cheat SheetsRabbitMQQueues

Queues — Cheat Sheet

RabbitMQ · 6 topics. Download the PDF or the Instagram carousel and share it.

Cheat Sheet · AiCanCode.org
Queues
RabbitMQ6 topicsQuick revision reference
1

Queue Declaration & Properties

Queues are declared with durable, exclusive, auto-delete, and argument flags; idempotent declaration ensures the queue exists before producers publish.

  • Queue declaration is idempotent; re-declaring with different properties raises a channel error
  • durable=true survives broker restart; durable=false (transient) is lost on restart
  • exclusive=true limits the queue to the declaring connection; deleted when connection closes
  • auto-delete=true deletes the queue when the last consumer disconnects
  • Arguments (x-message-ttl, x-max-length, x-dead-letter-exchange) add extended behaviour
  • RabbitAdmin in Spring auto-declares all Queue/Exchange/Binding beans at startup
Java — QueueBuilder with arguments
@Configuration
public class QueueConfig {

    // Standard durable work queue
    @Bean
    public Queue ordersQueue() {
        return QueueBuilder.durable("orders.processing")
            .withArgument("x-message-ttl", 600_000)      // 10 min TTL
            .withArgument("x-max-length", 50_000)        // max 50k messages
            .withArgument("x-dead-letter-exchange", "orders.dlx")
            .build();
    }

    // Transient queue — lost on broker restart
    @Bean
    public Queue tempQueue() {
        return QueueBuilder.nonDurable("orders.temp").build();
    }
}
2

Durable vs Transient Queues

Durable queues survive broker restart; transient queues are lost on restart. Combine durable queues with persistent message delivery mode for full data safety.

  • Durability = queue survives restart (declaration persisted); persistence = message survives restart (delivery-mode=2)
  • Both must be set together for full data safety — one without the other still risks data loss
  • Transient queues are faster (no disk I/O) and suit ephemeral patterns like RPC reply queues
  • Classic durable queues have a brief data-loss window under power failure — quorum queues do not
  • Quorum queues (3.8+) use Raft replication across nodes; recommended for business-critical data
  • Quorum queues do not support per-message TTL, exclusive, or non-durable configurations
Java — durable queue + persistent message delivery mode
@Bean
public Queue ordersDurableQueue() {
    return QueueBuilder.durable("orders.processing").build();
    // durable=true by default in QueueBuilder.durable()
}

// Publishing with persistent delivery mode
@Autowired RabbitTemplate rabbitTemplate;

public void publishOrder(OrderEvent event) {
    rabbitTemplate.convertAndSend("orders", "order.created", event, message -> {
        message.getMessageProperties()
               .setDeliveryMode(MessageDeliveryMode.PERSISTENT);
        return message;
    });
}
3

Exclusive & Auto-Delete Queues

Exclusive queues are accessible by a single connection and deleted when it closes; auto-delete queues are deleted when the last consumer unsubscribes — ideal for temporary reply queues.

  • Exclusive queue: only the declaring connection can use it; deleted when that connection closes
  • Auto-delete queue: deleted when the last consumer unsubscribes (must have had at least one)
  • RPC reply queues are the canonical use case for exclusive + auto-delete queues
  • Auto-delete fanout subscriber queues prevent stale message accumulation for absent subscribers
  • Exclusive queues cannot be shared across connections — use durable queues for shared consumers
  • An auto-delete queue that never had a consumer is NOT automatically deleted
Java — exclusive reply queue for RPC pattern
// RPC client — declare a unique exclusive reply queue
String replyQueueName = channel.queueDeclare().getQueue(); // auto-named, exclusive, auto-delete
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
    .correlationId(UUID.randomUUID().toString())
    .replyTo(replyQueueName)
    .build();
channel.basicPublish("", "rpc.requests", props, request.getBytes());

// Spring AMQP RPC — RabbitTemplate handles reply queue automatically
Object response = rabbitTemplate.convertSendAndReceive(
    "rpc.requests", requestPayload);
4

Bindings & Routing Keys

A binding connects an exchange to a queue with an optional routing key; a queue can have multiple bindings from different exchanges to receive diverse message streams.

  • A binding is a rule: exchange + routing key pattern → queue
  • Direct exchange: exact routing key match; Topic exchange: * (one word), # (zero or more)
  • Fanout exchange ignores routing keys and delivers to all bound queues
  • One queue can have multiple bindings — from multiple exchanges or multiple routing keys
  • One routing key can route to multiple queues (multicast) on a direct/topic exchange
  • Bindings are declared in Spring AMQP via Binding beans and auto-applied by RabbitAdmin
Java — direct exchange bindings
@Configuration
public class BindingConfig {

    @Bean DirectExchange ordersExchange() { return new DirectExchange("orders"); }
    @Bean Queue newOrderQueue()           { return QueueBuilder.durable("orders.new").build(); }
    @Bean Queue cancelQueue()             { return QueueBuilder.durable("orders.cancel").build(); }

    // Exact-match binding: routing key "order.created" → orders.new
    @Bean
    Binding newOrderBinding(Queue newOrderQueue, DirectExchange ordersExchange) {
        return BindingBuilder.bind(newOrderQueue).to(ordersExchange).with("order.created");
    }

    // Exact-match binding: routing key "order.cancelled" → orders.cancel
    @Bean
    Binding cancelBinding(Queue cancelQueue, DirectExchange ordersExchange) {
        return BindingBuilder.bind(cancelQueue).to(ordersExchange).with("order.cancelled");
    }
}
5

Message Properties

AMQP properties include delivery-mode (persistent/transient), content-type, correlation-id, reply-to, expiration, headers, and priority — all set by the producer per message.

  • delivery-mode=2 (PERSISTENT) is required for messages to survive broker restart
  • correlation-id + reply-to together implement the RPC/request-reply pattern
  • expiration is per-message TTL in milliseconds as a String (independent of queue x-message-ttl)
  • headers is a Map<String,Object> for arbitrary application-level metadata
  • priority (0-9) is honoured only if the queue was declared with x-max-priority argument
  • Use @Header annotation in @RabbitListener to extract individual properties cleanly
Java — setting MessageProperties via PostProcessor
rabbitTemplate.convertAndSend("orders", "order.created", event, message -> {
    MessageProperties props = message.getMessageProperties();
    props.setDeliveryMode(MessageDeliveryMode.PERSISTENT);   // survive restart
    props.setContentType("application/json");
    props.setMessageId(UUID.randomUUID().toString());
    props.setCorrelationId(requestContext.getTraceId());
    props.setExpiration("60000");                            // 60s per-message TTL
    props.setHeader("source-service", "order-service");
    props.setHeader("schema-version", "2");
    return message;
});
6

Message Persistence

Set delivery_mode=2 (persistent) on messages AND use a durable queue to survive broker restart; fsync overhead makes persistent messages slower than transient ones.

  • Both queue durability AND message delivery_mode=2 are required — one without the other is not persistence.
  • Persistent messages add latency because RabbitMQ must fsync before acknowledging; batch fsyncing mitigates this.
  • Publisher confirms provide at-least-once delivery: only send after the broker confirms disk write.
  • Classic mirrored queues are deprecated since RabbitMQ 3.9; use Quorum queues for replicated persistence.
  • Quorum queues require a majority of replicas to be available — plan your cluster size (3 or 5 nodes) accordingly.
  • For very high throughput, consider separating persistent critical queues (payments) from transient queues (logs) on different vhosts.
Java — durable queue + persistent message delivery
@Configuration
public class RabbitConfig {

    // durable=true: queue survives broker restart
    // autoDelete=false: not deleted when last consumer disconnects
    @Bean
    public Queue ordersQueue() {
        return QueueBuilder.durable("orders.queue")
                .withArgument("x-queue-type", "quorum") // Recommended: quorum queue
                .build();
    }
}

// Publishing a persistent message
rabbitTemplate.convertAndSend("orders.exchange", "new-order", event, message -> {
    message.getMessageProperties()
           .setDeliveryMode(MessageDeliveryMode.PERSISTENT); // delivery_mode=2
    return message;
});

// Or use the built-in MessagePostProcessor shorthand
rabbitTemplate.convertAndSend("orders.exchange", "new-order",
        event, new MessagePostProcessor() {
    @Override
    public Message postProcessMessage(Message msg) {
        msg.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
        return msg;
    }
});
Learn this free with Aria, your AI tutor → AiCanCode.org/learn/rabbitmq