Networking
AMQP — Advanced Message Queuing Protocol
A message-broker protocol like MQTT, but built around a more explicit model: routing (deciding where a message goes) is a separate concept from queuing (storing it until a consumer is ready), which is what makes complex fan-out and filtering rules possible without every consumer needing its own bespoke topic scheme.
- What it is
- A message-broker protocol that separates routing (exchanges) from storage (queues), enabling flexible fan-out rules.
- Mental model
- A sorting office: producers drop mail at an exchange, routing rules decide which mailboxes (queues) get a copy, consumers collect from their own mailbox whenever ready.
- Key numbers
- 4 exchange types (direct, topic, fanout, headers); durable queues survive broker restarts.
- Reach for it when
- You need complex routing or guaranteed persistence beyond what a flat topic hierarchy gives you.
Exchanges, queues, and bindings
Where MQTT has publishers, a broker, and topic subscriptions all in one flat concept, AMQP (0-9-1, the model RabbitMQ made popular) splits it into three explicit pieces:
- Exchange
- What a producer actually publishes to. It receives a message and a routing key, and decides — based on its type and its bindings — which queue(s), if any, get a copy.
- Queue
- Where messages actually sit until a consumer reads them. Independent of any exchange — the same queue can be bound to multiple exchanges, or none.
- Binding
- A rule connecting an exchange to a queue, usually with a routing key or pattern that decides which messages cross that link.
Exchange types
| Type | Routing rule |
|---|---|
| direct | Delivers to queues whose binding key exactly matches the message's routing key. |
| topic | Pattern matching on a dot-separated routing key using * (one word) and # (zero or more words) — the same flavor of hierarchy as MQTT topics, but as one exchange type among several rather than the whole model. |
| fanout | Ignores the routing key entirely; delivers to every queue bound to the exchange — the direct equivalent of broadcast. |
| headers | Routes based on message header attributes instead of the routing key, for matching that doesn't fit into a simple string pattern. |
Acknowledgements and delivery guarantees
A consumer explicitly acknowledges a message once it's safely processed; an unacknowledged message (consumer crashed, connection dropped) gets redelivered — the same at-least-once shape as MQTT QoS 1, but paired with genuine persistent queuing: a durable queue holding a persistent message survives a broker restart, so nothing is lost even if no consumer is online when it's published. Producers can request publisher confirms to know a message was safely accepted by the broker before considering the publish complete.
Connections and channels
Opening a fresh TCP connection per logical stream is expensive, so AMQP multiplexes many lightweight channels over a single TCP connection — each channel behaves like its own independent session (its own publishes, consumes, acknowledgements) without paying for a new handshake and connection-level overhead every time.
0-9-1 vs. 1.0 — two different protocols, one name
"AMQP" in casual conversation almost always means AMQP 0-9-1 — the exchange/queue/binding model above, and what RabbitMQ implements natively. AMQP 1.0 is a different, later, OASIS-standardized wire protocol — leaner, more focused purely on message transfer semantics, without mandating the exchange/queue model as part of the wire format itself (a broker can still implement that model on top of it). It's used by Azure Service Bus, ActiveMQ Artemis, and Solace, among others. The two are not wire-compatible — check which one a given broker or client library actually speaks before assuming interoperability.
AMQP vs. MQTT vs. CoAP
| AMQP | MQTT | CoAP | |
|---|---|---|---|
| Routing model | Exchanges + queues + bindings — flexible, multiple exchange types | Flat topic hierarchy with wildcards | REST resources, no broker |
| Persistence | Durable queues survive broker restarts natively | Retained messages (single latest value per topic), broker-dependent persistence | None — stateless request/response |
| Typical deployment | Enterprise/backend messaging, service-to-service integration | IoT device fleets, telemetry fan-out | Individually constrained embedded devices |
| Client weight | Heavier — assumes a capable client and stable connection | Light enough for small MCUs with networking | Lightest — designed for the smallest nodes |
On an embedded device, AMQP is far more often found at the backend end of a pipeline (a gateway or server ingesting device data) than running directly on the constrained device itself — that role usually falls to CoAP or MQTT.
Real-world applications
- Backend microservice communication — RabbitMQ (AMQP 0-9-1) is a standard choice for decoupling services in enterprise and cloud backends.
- Order/payment processing pipelines — durable queues and publisher confirms make AMQP a common choice wherever a message genuinely cannot be lost.
- IoT device gateways — a gateway ingesting MQTT or CoAP traffic from constrained devices commonly republishes it internally over AMQP for backend processing and routing.
- Azure Service Bus / cloud messaging — AMQP 1.0 is the wire protocol behind several major cloud messaging services.
Gotchas
- A queue with no consumers and no length/TTL limit grows without bound if producers keep publishing — set queue limits and dead-letter exchanges deliberately, don't rely on consumers always keeping up.
- "AMQP" without a version number is genuinely ambiguous — confirm 0-9-1 vs. 1.0 before assuming a client library and broker will actually interoperate.
- An exchange with no matching binding for a given routing key silently drops the message — there's no error by default, so a "message never arrived" bug is often a missing or misconfigured binding, not a broker or network problem.