AMQP 0-9-1 Model
IntermediateAMQP defines exchanges (routing), queues (storage), and bindings (rules); publishers target exchanges, consumers subscribe to queues — the model decouples routing from storage.
Overview
AMQP 0-9-1 (Advanced Message Queuing Protocol) is the wire-level protocol that RabbitMQ implements. The model has three core entities: Exchanges (receive messages from producers and route them), Queues (store messages until consumed), and Bindings (rules that connect exchanges to queues). This separation means routing logic lives in the broker, not the producer — producers do not need to know which queues exist. The protocol also defines Channels (lightweight virtual connections multiplexed over one TCP connection), Virtual Hosts, and Connection semantics.
Entities: Exchange, Queue, Binding
Exchanges receive messages from producers. Bindings link exchanges to queues with optional routing keys. Queues buffer messages until consumed. A message travels: Producer → Exchange → (Binding rule matches) → Queue → Consumer.
// 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");
}
}Channels & Connections
A Connection is a TCP connection to the broker. A Channel is a lightweight virtual connection multiplexed over one TCP connection. Use separate channels per thread — channels are not thread-safe. CachingConnectionFactory in Spring AMQP manages a pool of channels.
// AMQP Connection vs Channel hierarchy:
// TCP Connection (1 per application instance, expensive)
// └── Channel 1 (thread 1 — consumer)
// └── Channel 2 (thread 2 — producer)
// └── Channel 3 (thread 3 — another consumer)
// Channels are cheap (hundreds per connection); connections are expensive
// Spring AMQP CachingConnectionFactory — manages connection + channel pool
@Bean
public CachingConnectionFactory connectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory("localhost", 5672);
factory.setUsername("admin");
factory.setPassword("secret");
// Channel caching (default CHANNEL mode — pool of cached channels)
factory.setChannelCacheSize(25); // cache up to 25 channels
// Or CONNECTION mode — pool of connections (for multi-threaded high-load)
factory.setCacheMode(CachingConnectionFactory.CacheMode.CONNECTION);
factory.setConnectionCacheSize(5);
return factory;
}
// Never share a Channel across threads — always use separate channels
// Spring AMQP handles this automatically via CachingConnectionFactoryMessage Lifecycle & Guarantees
AMQP supports mandatory flag (error if no queue matches), publisher confirms (broker ACK), and consumer acknowledgements. Combined with durable exchanges, durable queues, and persistent delivery mode, messages survive broker restarts.
// Message durability stack:
// ✓ Durable exchange: survives broker restart
// ✓ Durable queue: survives broker restart
// ✓ Persistent message (delivery-mode=2): message body saved to disk
// All three required for full durability guarantee
// Mandatory flag — error if message is unroutable
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnsCallback(returned -> {
log.error("Message returned — unroutable: exchange={}, routingKey={}, replyCode={}",
returned.getExchange(), returned.getRoutingKey(), returned.getReplyCode());
// Re-route to DLX or alert on-call
});
// Publish a persistent message
rabbitTemplate.convertAndSend("orders", "order.placed", event, msg -> {
msg.getMessageProperties()
.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
msg.getMessageProperties()
.setContentType("application/json");
return msg;
});Key Points to Remember
- 1AMQP entities: Exchange (route), Queue (store), Binding (rule connecting exchange to queue).
- 2Producers publish to exchanges — they never reference queues directly.
- 3A Channel is a lightweight virtual connection over one TCP Connection — use one per thread.
- 4CachingConnectionFactory pools channels — never create raw channels manually.
- 5Full durability requires: durable exchange + durable queue + persistent delivery mode.
- 6Mandatory flag + returns callback catches unroutable messages before they are silently dropped.
Interview Questions
Sign in to ask AriaWhat is the difference between an AMQP Connection and a Channel?
Why is it important not to share a Channel across threads?
What three components must all be durable for a message to survive a broker restart?
What does the mandatory flag do in AMQP?
How does CachingConnectionFactory optimise connection usage in Spring AMQP?
Ask Aria about AMQP 0-9-1 Model
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.