Fundamentals — Cheat Sheet
RabbitMQ · 6 topics. Download the PDF or the Instagram carousel and share it.
RabbitMQ & AMQP Introduction
RabbitMQ is an open-source message broker implementing AMQP 0-9-1; producers publish messages to exchanges, which route them to queues consumed by subscribers.
- ✓Producers publish to exchanges, not queues — exchanges route via binding rules.
- ✓Four exchange types: direct (exact match), fanout (broadcast), topic (wildcard), headers.
- ✓Durable queues survive broker restart; persistent messages survive broker restart.
- ✓Manual ack ensures messages are removed only after successful processing.
- ✓nack with requeue=true returns the message to the front of the queue.
- ✓Dead-letter exchange (DLX) captures nacked or expired messages for inspection or retry.
// AMQP model overview:
//
// Producer
// │ publish(exchange="orders", routingKey="order.placed", body)
// ▼
// Exchange (orders) ← routing rules
// │ binding key="order.placed" → Queue: "order-processor"
// │ binding key="order.*" → Queue: "order-audit-log"
// ▼
// Queue (order-processor)
// │ deliver
// ▼
// Consumer (inventory-service)
// Spring Boot connection
// application.properties
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=secret
spring.rabbitmq.virtual-host=/
// Declare exchange, queue, and binding with Spring AMQP
@Configuration
public class RabbitConfig {
@Bean public TopicExchange ordersExchange() {
return new TopicExchange("orders");
}
@Bean public Queue orderProcessorQueue() {
return QueueBuilder.durable("order-processor").build();
}
@Bean public Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with("order.placed");
}
}RabbitMQ vs Kafka
RabbitMQ excels at complex routing, priority queues, and task distribution with message acknowledgement; Kafka excels at high-throughput event log replay and stream processing.
- ✓RabbitMQ: push-based, messages deleted after ack, exchange routing, task queues
- ✓Kafka: pull-based, append-only log, message retained regardless of consumption, replay
- ✓Multiple Kafka consumer groups read the same topic independently at their own pace
- ✓RabbitMQ supports complex routing (topic, headers exchange), priority, TTL, and RPC patterns
- ✓Kafka is designed for millions of messages/sec; RabbitMQ peaks at tens of thousands
- ✓Use RabbitMQ for routing/tasks; use Kafka for streaming, event sourcing, and audit logs
// RabbitMQ model — message deleted after ack
Producer → Exchange (routing) → Queue → Consumer (ack → message gone)
→ Consumer2 (same queue = competing consumers)
// Kafka model — message retained in immutable log
Producer → Topic (partition) → Log (offset 0, 1, 2, 3, ...)
↑
Consumer Group A: reads offset 5 (order processing)
Consumer Group B: reads offset 3 (analytics — lags behind, replays)
Consumer Group C: reads from offset 0 (audit replay)
// Key insight: RabbitMQ delivers, Kafka stores; consumers pull from KafkaProducers, Consumers & Brokers
Producers publish messages to an exchange; the broker routes them to bound queues; consumers subscribe to queues and process messages, optionally acknowledging completion.
- ✓Producers publish to exchanges — never directly to queues.
- ✓The broker routes messages from exchanges to queues via binding rules.
- ✓Consumers subscribe to queues; the broker pushes messages to them.
- ✓A message stays in the queue until the consumer sends basicAck.
- ✓Unacked messages are redelivered when the consumer channel closes.
- ✓Spring AMQP AUTO ack mode: ack on return, nack on exception (requeues by default).
// Spring Boot producer — complete flow
@Configuration
public class RabbitConfig {
@Bean
public TopicExchange ordersExchange() {
return ExchangeBuilder.topicExchange("orders")
.durable(true).build();
}
@Bean
public MessageConverter jsonConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory cf,
MessageConverter converter) {
RabbitTemplate t = new RabbitTemplate(cf);
t.setMessageConverter(converter);
t.setConfirmCallback((cd, ack, cause) -> {
if (!ack) log.error("Publish NACK: {}", cause);
});
return t;
}
}
@Service
public class OrderProducer {
private final RabbitTemplate rabbitTemplate;
public void publishOrderPlaced(OrderEvent event) {
// exchange="orders", routingKey="order.placed", body=JSON(event)
rabbitTemplate.convertAndSend("orders", "order.placed", event);
}
}Virtual Hosts (vhosts)
vhosts provide logical namespacing within a single RabbitMQ instance; exchanges, queues, and bindings in one vhost are completely isolated from another.
- ✓Vhosts provide complete isolation: exchanges, queues, and bindings are scoped to a single vhost
- ✓Default vhost is "/"; connect with virtual-host: / in Spring or amqp://host/vhost in URIs
- ✓User permissions are per-vhost with configure (declare), write (publish), read (consume) regexes
- ✓Use vhosts for environment separation (dev/staging) or team isolation on a shared broker
- ✓Policies (TTL, max-length, HA) are applied at vhost level and affect only resources within it
- ✓Vhost limits (max-connections, max-queues) prevent one tenant from monopolising broker resources
# Create a vhost
rabbitmqctl add_vhost orders
# Grant user "order-svc" full access to /orders vhost
rabbitmqctl set_permissions -p orders order-svc ".*" ".*" ".*"
# Connection URI with vhost
# amqp://user:password@host:5672/orders
# Spring Boot application.yml
spring:
rabbitmq:
host: rabbitmq.internal
port: 5672
username: order-svc
password: secret
virtual-host: ordersConnections & Channels
A connection is a TCP socket; channels are lightweight multiplexed virtual connections within it. Open one connection per process and multiple channels per thread to avoid overhead.
- ✓One TCP connection per process; one channel per thread — violating this causes frame corruption or excessive socket overhead.
- ✓Channels are cheap (in-memory multiplexing); connections are expensive (TCP + TLS handshake + authentication).
- ✓Spring AMQP's CachingConnectionFactory handles pooling transparently — prefer it over manual connection management.
- ✓CHANNEL cache mode is fine for most apps; use CONNECTION mode when publisher confirms and consumers need channel isolation.
- ✓Heartbeats (default 60s) detect dead connections; without them, idle connections silently drop and cause message loss.
- ✓Monitor connection count and channel count via the RabbitMQ Management UI or Prometheus exporter.
# rabbitmq.conf
# Heartbeat: detect dead connections (default 60s)
heartbeat = 60
# Max channels per connection (default 2047)
channel_max = 128
# Max frame size
frame_max = 131072
---
# Java — raw AMQP client (educational; prefer Spring AMQP)
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setVirtualHost("/orders");
factory.setUsername("app");
factory.setPassword("secret");
// One connection per process
Connection connection = factory.newConnection();
// One channel per thread
Channel channel = connection.createChannel();
channel.basicPublish("orders.exchange", "new-order",
MessageProperties.PERSISTENT_TEXT_PLAIN,
body.getBytes());
channel.close(); // return to pool or close
connection.close();AMQP 0-9-1 Model
AMQP defines exchanges (routing), queues (storage), and bindings (rules); publishers target exchanges, consumers subscribe to queues — the model decouples routing from storage.
- ✓AMQP entities: Exchange (route), Queue (store), Binding (rule connecting exchange to queue).
- ✓Producers publish to exchanges — they never reference queues directly.
- ✓A Channel is a lightweight virtual connection over one TCP Connection — use one per thread.
- ✓CachingConnectionFactory pools channels — never create raw channels manually.
- ✓Full durability requires: durable exchange + durable queue + persistent delivery mode.
- ✓Mandatory flag + returns callback catches unroutable messages before they are silently dropped.
// AMQP entity relationships:
//
// VirtualHost "/" (logical namespace)
// │
// ├── Exchange: "orders" (type=topic)
// │ │
// │ ├── Binding: key="order.placed" ──────► Queue: "order-processor"
// │ ├── Binding: key="order.*" ──────► Queue: "order-audit"
// │ └── Binding: key="#" ──────► Queue: "order-archive" (all)
// │
// └── Exchange: "notifications" (type=fanout)
// │
// ├── Binding: (no key needed) ───► Queue: "email-notifications"
// └── Binding: (no key needed) ───► Queue: "sms-notifications"
// Spring AMQP — declare entities
@Configuration
public class AmqpTopology {
@Bean public TopicExchange ordersExchange() {
return ExchangeBuilder.topicExchange("orders").durable(true).build();
}
@Bean public Queue orderProcessorQueue() {
return QueueBuilder.durable("order-processor").build();
}
@Bean public Binding orderProcessorBinding(Queue q, TopicExchange ex) {
return BindingBuilder.bind(q).to(ex).with("order.placed");
}
}