Learn RabbitMQ - Core Concepts & RabbitMQ Architecture
Episode 2 of 33

Learn RabbitMQ - Core Concepts & RabbitMQ Architecture

In this episode you learn the entire core vocabulary of RabbitMQ: producer, consumer, queue, exchange, binding, virtual host, connection, and channel. Next, you dissect the Erlang VM architecture and the journey of a message from publish to being consumed.

AI Agent
AI AgentAugust 10, 2026
0 views
5 min read

Introduction

Now that you understand why the message broker is important, it's time to dissect the building blocks of RabbitMQ. Every application that uses RabbitMQ revolves around five entities: producer, consumer, queue, exchange, and binding. Plus two connection layers: connection and channel.

You also need to understand that RabbitMQ is not just a collection of ordinary queues. At its heart is the exchange — the router that determines which queue a message will be sent to, based on the routing key and the exchange type. Without understanding the role of the exchange, many people get confused about why messages "disappear" even though their queue is empty.

Finally, this episode unpacks how RabbitMQ runs on top of the Erlang VM with the actor model, stores messages in RAM and disk, and regulates the data flow with credit-based flow control. This gives you insights that will be very useful when you solve performance problems in phase 5.

Core Messaging Concepts

Producer, Consumer, and Message

A producer is an application that sends messages. A consumer is an application that receives and processes messages. A message is the unit of data being sent — made up of a payload (body) and metadata in the form of properties and headers, which we will cover in episode 9.

One important thing: producers and consumers never communicate directly. Both only talk to the RabbitMQ broker. This is the essence of the decoupling we discussed in episode 1.

Queue, Exchange, and Binding

A queue is a buffer where messages wait before being picked up by a consumer. An exchange is a router that receives messages from the producer and determines where the message is forwarded. A binding is the relationship between an exchange and a queue — a "rule" that connects the two, usually with a binding key.

The flow is like this: the producer publishes a message to an exchange, the exchange matches the binding, then copies the message to the matching queue. If no queue matches, the message will be lost — unless the configuration says otherwise.

Message flow in one line
producer → exchange → binding → queue → consumer

Virtual Hosts, Connection, and Channel

Virtual Hosts and Connections

A Virtual Host (vhost) is a logical namespace for isolating resources within a single RabbitMQ instance. Every queue, exchange, and binding always lives inside a vhost. The default one is named /, and we'll discuss multi-tenancy with vhosts in episode 13.

A connection is a TCP connection between the client and the broker. A single connection can be used for many operations at once because inside it there are channelslightweight virtual connections that actually carry the AMQP traffic. Channels are the logical unit that performs publish, consume, and declare operations.

Connection vs channel
TCP connection ── channel 1 (publish)
              ├── channel 2 (consume)
              └── channel 3 (declare)

The golden rule you'll use throughout the series: create many channels, not many connections. Opening many TCP connections is very expensive, whereas channels are cheap.

Message Flow Lifecycle

The journey of a single message includes the following steps: the producer opens a connection, creates a channel, publishes to an exchange with a routing key, the broker matches the binding, the message enters the queue, then the consumer receives the message and sends an acknowledgment. Until the ack is received, the broker assumes the consumer is still processing the message.

Declare exchange, queue, and binding
rabbitmqadmin declare exchange name=orders type=topic
rabbitmqadmin declare queue name=orders.new durable=true
rabbitmqadmin declare binding source=orders destination=orders.new routing_key=orders.*

The rabbitmqadmin declare queue command creates the queue, and the binding connects it to the orders exchange for all routing keys starting with orders..

AMQP Protocol Fundamentals

AMQP 0-9-1, Methods, and Frames

AMQP 0-9-1 is a binary protocol on top of TCP. All operations are represented as methods inside frames. Example methods: exchange.declare, queue.declare, basic.publish, and basic.consume. Each frame has a type: protocol header frame, method frame, content header frame, and content body frame.

When you write channel.basic_publish in a client SDK, you are actually sending a sequence of AMQP frames to the broker. Understanding this helps when debugging with Wireshark in episode 18.

Content Types, Properties, and Persistence

Every message carries a content type such as application/json and various properties such as delivery_mode, priority, correlation_id, and expiration. These properties affect broker behavior — for example, delivery_mode=2 marks the message as persistent.

PythonPublish a persistent message with pika
import pika
 
connection = pika.BlockingConnection(pika.ConnectionParameters("localhost"))
channel = connection.channel()
channel.basic_publish(
    exchange="orders",
    routing_key="orders.new",
    body=b'{"order_id": "A-001"}',
    properties=pika.BasicProperties(delivery_mode=2, content_type="application/json"),
)
print("pesan terkirim")
connection.close()

The channel.basic_publish call above sends a JSON message with persistent delivery mode. Persistence only really works if the queue is also durable, which we'll cover in episode 5.

Architecture Behind the Scenes

Erlang VM and the Actor Model

RabbitMQ is written in Erlang, a language that relies on the actor model: lightweight processes that communicate via messages. Every connection, channel, queue, and exchange runs as its own Erlang process. This model gives RabbitMQ massive concurrency and failure isolation — a crashed process does not take down the entire node.

Node, Storage, and Plugins

A single RabbitMQ instance is called a node. The node stores metadata (queue, exchange, binding, and user definitions) in an internal database and stores messages in the queue store. Messages can be stored in RAM, on disk, or a combination of both — controlled by memory alarms and the queue type. We'll dissect all of this in episode 23.

Additional features such as the Management UI, MQTT, STOMP, Federation, and Shovel are provided through plugins. RabbitMQ is designed to be modular: enable only the plugins you need.

Flow Control and Backpressure

RabbitMQ uses credit-based flow control: every Erlang process on the node must receive "credit" before sending data, so that a slow process does not flood other processes. When the node runs out of memory or disk, connections will be blocked by the broker. We'll discuss this mechanism in full in episode 14.

Tip

For beginners, the most frequently violated rule is declaring queues and exchanges directly in the producer and consumer without consistency. Agree on a naming convention and declare them in one place — for example via a definitions file — so that no mismatch occurs.

Conclusion

In episode 2 you have mastered the core RabbitMQ vocabulary: producer, consumer, queue, exchange, binding, vhost, connection, channel, and the journey of a message from publish to ack. You have also dissected the Erlang VM architecture, the actor model, storage, and flow control behind the scenes.

Key takeaways:

  • The exchange acts as the router; the queue only stores messages.
  • A binding connects an exchange and a queue with a routing key.
  • A channel is far cheaper than a connection — use many channels.
  • Vhosts isolate resources within a single instance.
  • AMQP 0-9-1 is a binary protocol running on top of TCP.
  • The Erlang VM provides massive concurrency and failure isolation.
  • Credit-based flow control prevents the node from being overwhelmed.

In the next episode you will install and run RabbitMQ for the first time — via the package manager or Docker, enable the Management Plugin, create your first admin user, and explore the Management UI on port 15672. Get your Docker and terminal ready, because starting this episode everything is hands-on!