Theory Exchanges Binding Queue
RABBITMQ CHECKPOINT – CONSOLIDATED
- WHAT IS A MESSAGE
A message is a byte payload + metadata.
RabbitMQ does not understand business meaning.
Message meaning (command / event) is decided by the system design, not RabbitMQ.
A message always has:
-
body (bytes)
-
routing key (string)
-
optional headers
- WHAT IS RABBITMQ
RabbitMQ is a broker (separate server process).
Applications connect as clients.
RabbitMQ responsibilities:
-
accept messages
-
route messages
-
buffer messages
-
deliver messages
-
re-deliver on failure
RabbitMQ does NOT:
-
execute business logic
-
know what services exist
-
know what “invoice” means
-
CORE OBJECTS (ONLY THESE EXIST)
-
Exchange
-
Queue
-
Binding
-
Message
Everything else is convention.
- CORE FLOW (NON-NEGOTIABLE)
Producer → Exchange → Queue → Consumer
Rules:
-
Producers publish to exchanges
-
Consumers consume from queues
-
Consumers NEVER consume exchanges
-
Producers NEVER publish directly to queues
-
Bindings connect exchanges to queues
- EXCHANGE (WHAT IT IS)
An exchange:
-
does NOT store messages
-
applies ONE routing algorithm
-
routes messages to queues via bindings
An exchange answers:
“How do I match routing keys to bindings?”
Exchange types (REAL RabbitMQ types):
direct
-
exact match routing
-
routing_key == binding_key
topic
-
wildcard pattern routing
-
supports
*and#
fanout
-
ignores routing key
-
sends to ALL bound queues
headers
- matches on headers (rare)
ONE exchange = ONE routing algorithm
An exchange cannot mix routing behaviors.
- ROUTING KEY
Routing key:
-
string attached to message
-
interpreted by exchange
-
semantics decided by system design
Examples:
-
invoice.created
-
invoice.peppol.send
-
invoice.peppol.failed
Routing key does NOT decide exchange type.
- BINDING (ROUTING RULE)
Binding = routing rule
Binding lives inside RabbitMQ.
Mechanically:
(exchange + binding_key) → queue
Meaning:
“If a message matches this rule, put it in this queue.”
Bindings are data, not logic.
- QUEUE
Queue:
-
mailbox / buffer
-
stores messages
-
delivers to consumers
-
tracks ACKs
-
guarantees order per queue
Design rule:
ONE queue = ONE responsibility
If consumer has to inspect message type and branch → bad queue design.
- TOPIC WILDCARDS (ONLY FOR TOPIC EXCHANGE)
* = exactly one word
# = zero or more words
Routing key:
invoice.peppol.sent
Matches:
-
invoice.peppol.*
-
invoice.#
-
*.peppol.sent
Does NOT match:
-
invoice.sent
-
peppol.invoice.sent
- COMMAND VS EVENT (SEMANTIC DECISION)
RabbitMQ does NOT know commands or events.
Command:
-
intent: “do this”
-
exactly one handler
-
failure is critical
-
obligation
-
usually mapped to DIRECT exchange
Example:
SendInvoiceToPeppol
routing key: invoice.peppol.send
Event:
-
intent: “this happened”
-
zero or many consumers
-
no ownership
-
notification
-
usually mapped to TOPIC or FANOUT exchange
Example:
InvoiceCreated
routing key: invoice.created
Same routing key string can be used for either; intent decides correctness.
- FANOUT (BROADCAST)
Fanout exchange:
-
ignores routing key
-
STILL requires bindings
-
sends to ALL bound queues
Fanout ≠ “send to everything in RabbitMQ”
Fanout = “send to every queue bound to this exchange”.
- TOPOLOGY EXAMPLE (SINGLE SYSTEM)
Exchanges:
-
invoice.command (direct)
-
invoice.event (topic)
-
invoice.broadcast (fanout)
Queues:
-
peppol-command-queue
-
email-command-queue
-
audit-event-queue
-
analytics-event-queue
-
websocket-queue
-
cache-queue
Bindings:
invoice.command
-
invoice.peppol.send → peppol-command-queue
-
invoice.email.send → email-command-queue
invoice.event
-
invoice.created → analytics-event-queue
-
invoice.# → audit-event-queue
invoice.broadcast
-
→ websocket-queue
-
→ cache-queue
- MESSAGE ROUTING EXAMPLES
Publish:
exchange = invoice.command
routing key = invoice.peppol.send
Result:
- delivered ONLY to peppol-command-queue
Publish:
exchange = invoice.event
routing key = invoice.created
Result:
-
delivered to analytics-event-queue
-
delivered to audit-event-queue
Publish:
exchange = invoice.broadcast
Result:
-
delivered to websocket-queue
-
delivered to cache-queue
- CONSUMPTION RULE
Services:
-
declare queues
-
declare bindings
-
consume queues
Services DO NOT:
-
subscribe to exchanges
-
know who else consumes
- WHY BINDINGS APPEAR IN CODE
Bindings live in RabbitMQ.
Code only sends API requests like:
“Ensure this exchange/queue/binding exists.”
This is equivalent to DB migrations.
Topology becomes broker state.
-
FINAL INVARIANTS
-
Exchange defines HOW routing works
-
Binding defines WHERE messages go
-
Queue defines WHO handles messages
-
One exchange = one routing algorithm
-
Direct = obligation
-
Topic = notification
-
Fanout = broadcast
-
Meaning comes from intent, not syntax
END CHECKPOINT