Core Concepts
Connections and channels
Section titled “Connections and channels”A client talks to RabbitMQ over a single long-lived TCP connection. But opening a TCP connection is expensive, and a busy app needs to do many things at once — publish from one place, consume in another, several threads working in parallel.
The answer is channels. A channel is a lightweight virtual connection multiplexed over one TCP connection. You open one connection per process and many channels over it — typically one channel per thread or per concurrent task.
flowchart LR app["Application"] --> conn["1 TCP Connection"] conn --> ch1["Channel 1 (publisher)"] conn --> ch2["Channel 2 (consumer)"] conn --> ch3["Channel 3 (consumer)"] ch1 --> broker["RabbitMQ"] ch2 --> broker ch3 --> broker
The rule of thumb: connections are long-lived and few; channels are cheap and many. A common mistake is opening a connection per operation — that exhausts the broker. Another is sharing one channel across threads — channels are not thread-safe. One connection per app, one channel per worker.
Exchanges, queues, and bindings
Section titled “Exchanges, queues, and bindings”You met these last lesson; here is the precise version:
- An exchange receives every published message and, using its type and its bindings, decides which queues get it. It stores nothing.
- A queue is an ordered buffer that holds messages until a consumer takes them. This is the only thing that stores messages.
- A binding connects an exchange to a queue. It may carry a binding key that, combined with the message’s routing key, determines whether a message matches.
The routing key is just a string label the producer puts on each message (like order.created or payment.failed). Whether it matters depends on the exchange type — a fanout exchange ignores it entirely, a topic exchange pattern-matches on it. That’s the whole Exchanges & Routing module.
The journey of one message
Section titled “The journey of one message”Put it together and trace a single message end to end:
sequenceDiagram participant P as Producer participant X as Exchange participant Q as Queue participant C as Consumer P->>X: publish(routing key, body) X->>Q: route by binding Note over Q: message waits here Q->>C: deliver C->>C: process C->>Q: ack (I'm done) Note over Q: message removed
- The producer publishes a message with a routing key to an exchange.
- The exchange routes it to matching queues (zero, one, or many).
- The message waits in the queue until a consumer is ready.
- The queue delivers it to a consumer.
- The consumer processes it and sends an acknowledgement — only then does the queue delete it.
That last step is the safety net: until the consumer acks, RabbitMQ assumes the work isn’t done. If the consumer crashes mid-task, the un-acked message is redelivered. (An entire later lesson is devoted to acknowledgements — they are how “at-least-once” delivery works.)