Imagine a customer places an order. That single fact needs to reach a lot of places at once: the warehouse needs to pick it, finance needs to invoice it, the loyalty engine needs to award points, the analytics pipeline needs to count it, and the customer needs a confirmation email. The clumsy way to build this is to have the order service call each of those systems directly, one after another, and to edit that service every time a new consumer appears. The elegant way is to let the order service announce, once, that an order was placed, and to let every interested system listen for that announcement on its own terms. That announcement pattern is publish-subscribe, and it is the subject of this guide. It is one specific tool inside the wider discipline covered in the enterprise system integration pillar, and it is worth understanding on its own because it solves a problem almost every growing system eventually hits.
The idea in one line: in pub/sub, a publisher sends a message to a named topic, and the messaging system delivers a copy to every subscriber that has registered interest in that topic. The publisher does not know, and does not care, who the subscribers are or how many there are. That single property, the publisher not knowing its audience, is the whole point and the source of every benefit that follows.
1. What pub/sub is
Publish-subscribe, usually shortened to pub/sub, is a messaging pattern for distributing events to multiple interested parties. It has three roles. A publisher produces messages. A topic (sometimes called a channel or an exchange, depending on the platform) is the named destination those messages are sent to. A subscriber is a consumer that has registered interest in a topic and receives a copy of every message published to it. Sitting under all three is the broker or messaging service, the piece of infrastructure that accepts published messages and takes responsibility for delivering them to the right subscribers.
The word that defines the pattern is fan-out. One message published to a topic fans out to many subscribers, each of which gets its own independent copy. This is fundamentally different from a phone call or a direct function call, where the sender picks exactly one recipient and waits for it to respond. In pub/sub the sender broadcasts a fact to a topic and moves on, and the delivery of that fact to zero, one, or fifty listeners is the messaging system's job, not the publisher's.
It helps to think of the message as a statement of something that has happened, phrased in the past tense: "order placed," "payment captured," "device went offline," "meter reading recorded." The publisher is announcing a fact about the world. It is not issuing a command to a particular system, and it is not asking a question and waiting for an answer. That framing, events rather than commands, is what makes pub/sub such a natural fit for event-driven architecture, and it is closely related to the event handling you see with webhooks, where a source system pushes a notification the moment something occurs.
2. The decoupling it gives you
The reason architects reach for pub/sub is decoupling. When the order service calls the warehouse, the finance system, and the loyalty engine directly, it is tightly bound to all three. It needs their addresses, it needs to handle each one being slow or down, and every time the business adds a new consumer, the order service has to be reopened, changed, tested, and redeployed. The publisher becomes a bottleneck that grows more fragile with every integration bolted onto it.
Pub/sub cuts that binding. The order service publishes one "order placed" event to a topic and knows nothing about who consumes it. Adding a new subscriber, say a fraud-screening service six months later, requires no change whatsoever to the publisher. The new service simply subscribes to the topic and starts receiving events. The publisher and the subscribers evolve independently, which is exactly the property you want in a system that has to keep growing without a rewrite each time. The diagram below shows the shape of it: one publisher, one topic, and several independent subscribers each receiving their own copy.
Notice what the diagram does not show: any line between the publisher and the subscribers. They never touch. The topic is the only thing either side knows about, which is why you can add, remove, or restart any subscriber without the publisher noticing. That independence is not a side benefit, it is the reason the pattern exists.
3. Topics and subscriptions
The two nouns that do the real work in pub/sub are the topic and the subscription, and understanding the relationship between them clears up most of the confusion beginners have. A topic is a named stream of messages. A subscription is a named registration of interest against that topic. When a subscriber wants to receive a topic's messages, it creates or attaches to a subscription, and the broker uses that subscription to track which messages that particular consumer still needs to receive.
The important detail is that each subscription gets its own copy of every message and its own independent progress. If the warehouse subscription is running behind because the warehouse system was down for an hour, that has no effect on the finance subscription, which keeps receiving orders in real time. Each subscriber consumes at its own pace, and each one acknowledges messages independently. This is what lets a slow consumer and a fast consumer share the same topic without interfering with each other.
Most platforms also let you narrow a subscription with a filter. Rather than receiving every message on a topic, a subscription can specify that it only wants messages matching certain attributes, for example only orders above a certain value, or only events from a particular region. This keeps a busy topic useful to consumers that care about only a slice of it, without forcing publishers to split their events across many narrow topics. Some ecosystems take filtering further with hierarchical or wildcard topic names, so a subscriber can register interest in a whole family of topics such as all events under "sensors/building-a/" at once.
Design tip: name topics after business events, not after the systems that consume them. "order.placed" is a good topic name because it describes a fact that will always be true regardless of who listens. "send-to-warehouse" is a poor topic name because it bakes one consumer's intent into the topic, which quietly recreates the coupling you were trying to escape. Good topic names outlive the consumers around them.
4. Push versus pull delivery
Once a message is sitting in a subscription waiting to be delivered, there are two ways it can reach the subscriber, and the choice affects how you build the consumer. In push delivery, the broker actively sends the message to the subscriber, typically by calling an endpoint the subscriber exposed, such as an HTTP webhook. The subscriber does not have to ask; messages arrive as soon as they are available. This is convenient and low-latency, but it requires the subscriber to be reachable and to handle incoming traffic, and it means the broker controls the rate at which messages arrive.
In pull delivery, the subscriber asks the broker for messages when it is ready, receives a batch, processes them, and asks again. The subscriber controls its own pace, which makes pull the natural choice for high-throughput consumers and for workloads where you want to process messages in controlled batches. The cost is that the subscriber has to run an active loop that keeps requesting messages, and it has to manage its own polling behaviour so it neither hammers the broker nor falls behind.
Neither model is universally better. Push is simpler for lightweight, event-reactive consumers that want messages the instant they appear and do not expect heavy volume. Pull is stronger for consumers that need to control throughput, batch their work, or apply their own backpressure when they are overwhelmed. Many platforms support both and let each subscription choose. The one thing that stays constant across both is acknowledgement: whichever way a message is delivered, the subscriber must confirm it processed the message successfully, and until it does, the broker holds the message and will redeliver it. That acknowledgement step is what makes the reliability guarantees in section seven possible.
5. Pub/sub versus a point-to-point queue
The single most common confusion in messaging is between pub/sub and a plain point-to-point queue, because both involve a broker sitting between producers and consumers, and both let systems communicate without calling each other directly. The difference is in who receives each message. In a point-to-point queue, a message is delivered to exactly one consumer and then removed; if several workers share the queue, each message goes to just one of them, which is how you spread a workload across a pool. In pub/sub, a message is delivered to every subscription, so each interested system gets its own copy. Queues distribute work; topics broadcast events. For a deeper treatment of the queue side of this, see the message queue guide.
| Dimension | Publish-subscribe (topic) | Point-to-point (queue) |
|---|---|---|
| Delivery model | One message copied to every subscription (fan-out) | One message delivered to a single consumer, then removed |
| Number of consumers | Many independent subscribers, each sees all messages | Many competing workers, each message handled once |
| Coupling | Publisher unaware of consumers; add listeners freely | Producer targets one logical destination and its worker pool |
| Typical use case | Broadcast an event that many systems react to | Distribute a workload of tasks across workers |
In practice the two patterns are complementary, and mature architectures use both. A common shape is a topic that fans an event out to several subscriptions, where each subscription then behaves like a queue feeding a pool of competing workers for that one consumer. That way you get the broadcast at the top and the workload distribution at the bottom. Modern platforms often blend the two so cleanly that the line between them is a configuration choice rather than a separate product, but the mental model, broadcast versus distribute, is the thing to hold onto.
6. Common pub/sub platforms
The pattern is old, but the tooling around it is healthy and varied. A few of the platforms you will meet most often in enterprise work:
- Apache Kafka: a durable, high-throughput log-based platform. Consumers subscribe to topics and read from a retained, ordered log, which makes Kafka as much an event-streaming backbone as a classic pub/sub broker. It shines when you need durability, replay, and very high volume. Its streaming character is covered in the event streaming guide.
- RabbitMQ: a flexible broker built around exchanges and queues. It supports pub/sub through fan-out and topic exchanges and is a strong general-purpose choice when you want mature routing and both queue and topic behaviour in one place.
- Google Cloud Pub/Sub and Amazon SNS: fully managed cloud services that handle the broker for you and scale automatically. SNS is frequently paired with SQS queues to combine broadcast with per-consumer buffering, the topic-into-queue shape described above.
- Azure Service Bus: an enterprise messaging service with first-class topics and subscriptions, including rich subscription filters, widely used where systems already sit in the Microsoft ecosystem.
- MQTT brokers: a lightweight publish-subscribe protocol built for constrained devices and unreliable networks, which has made it the default messaging pattern in the Internet of Things, where thousands of sensors publish to topics that backend services subscribe to.
The right choice depends on your durability needs, your throughput, whether you want to run the broker yourself or consume it as a managed service, and what your surrounding platform already speaks. What matters more than the brand is that the pattern is the same across all of them: publishers, topics, subscriptions, and a broker that guarantees delivery.
7. Reliability, ordering and duplicate delivery
This is the section vendors gloss over and practitioners lose sleep over, so it deserves an honest treatment. Pub/sub gives you decoupling, but the guarantees around delivery are more subtle than "the message always arrives exactly once, in order." Get these wrong and you build subscribers that misbehave under load or during failures.
On delivery guarantees, most production systems offer at-least-once delivery. That means a message will be delivered, but under certain failure conditions, a broker crash mid-acknowledgement, a network hiccup, a redelivery timer firing, the same message can be delivered more than once. True exactly-once delivery is very hard in a distributed system and, where it is offered, it usually comes with constraints and cost. The practical answer is not to demand exactly-once from the infrastructure but to make your subscribers idempotent, meaning processing the same message twice produces the same result as processing it once. If "order placed" arrives twice, the loyalty engine should award the points once. Idempotency is the seatbelt that makes at-least-once delivery safe.
The honest caution: do not assume messages arrive exactly once or strictly in order just because the demo looked clean. Assume duplicates can happen and design every subscriber to handle them, usually by recording which message identifiers it has already processed and ignoring repeats. Teams that skip this ship subscribers that quietly double-charge, double-email, or double-count the moment the system experiences its first real failure, and those bugs are miserable to diagnose after the fact.
On ordering, the default in many pub/sub systems is that messages are not guaranteed to arrive in the order they were published, especially once throughput is spread across partitions or multiple delivery workers for parallelism. Where ordering matters, for example all events for one specific order need to be processed in sequence, platforms typically offer ordering within a partition or an ordering key, so messages sharing a key stay in order even though the topic as a whole does not. The tradeoff is that strict ordering limits how much you can parallelise, so you apply it only where the business genuinely needs it rather than everywhere by default.
Finally, plan for failure handling. When a subscriber cannot process a message after several attempts, you do not want it stuck redelivering forever and blocking everything behind it. The standard answer is a dead-letter destination, a separate topic or queue where poison messages are parked after a set number of failed attempts, so a human or an automated process can inspect them while the main flow keeps moving. A pub/sub design without a dead-letter strategy is a design that has not yet met its first malformed message.
8. When to use pub/sub
Pub/sub is powerful, but it is not the answer to every integration problem, and reaching for it reflexively adds a broker, operational overhead, and the eventual-consistency mindset that asynchronous messaging demands. It earns its place when the following are true.
- One event genuinely has many interested consumers. The moment a single fact needs to reach three or more systems, and especially when you expect that list to keep growing, pub/sub pays for itself by removing the publisher from the equation.
- You want the publisher and consumers to evolve independently. If you are tired of reopening a core service every time a new downstream need appears, a topic lets new subscribers attach without touching the source.
- The interaction is a notification, not a request for an answer. Pub/sub fits "this happened, react if you care." It does not fit "do this and tell me the result right now," which is the job of a synchronous API call.
- You can tolerate asynchronous, eventually-consistent processing. Subscribers act shortly after the event, not in the same instant, so any flow that demands an immediate, confirmed, all-or-nothing outcome across systems is a poor fit.
Conversely, if only one system consumes an event, a direct API call or a point-to-point queue is simpler and honest about the coupling that already exists. And where you need a caller to receive a result synchronously, a request-response API is the right tool, not a topic. In the systems I work on, pub/sub, queues, and synchronous APIs coexist happily: the API handles the immediate request, the queue distributes the heavy work, and the topic broadcasts the resulting event to everyone else who needs to know. A concrete example of this blend is how business events flow out of an ERP into surrounding systems, which I cover in the Business Central APIs and integrations guide, where webhooks and event subscriptions turn ERP changes into signals the rest of the estate can react to.
9. References
For readers who want to go deeper into the pattern and the platforms, these are solid, non-marketing sources worth your time:
- Gregor Hohpe and Bobby Woolf, Enterprise Integration Patterns, which defines the Publish-Subscribe Channel and the surrounding messaging patterns in careful detail.
- Martin Kleppmann, Designing Data-Intensive Applications, for the chapters on messaging, streams, and the delivery and ordering guarantees discussed above.
- The Apache Kafka documentation, for the log-based take on topics, partitions, consumer groups, and ordering keys.
- The RabbitMQ documentation, for exchanges, topic and fan-out routing, and dead-letter handling.
- The Google Cloud Pub/Sub and Amazon SNS product documentation, for managed push and pull delivery, subscription filters, and at-least-once semantics.
- The OASIS MQTT specification, for the lightweight publish-subscribe protocol used across the Internet of Things.
Final thoughts
Pub/sub is one of those patterns that looks almost too simple when you first meet it and then quietly reshapes how you design systems once it clicks. Strip away the platforms and the terminology and it comes down to a single, powerful idea: a publisher announces that something happened, and the messaging system takes responsibility for delivering that fact to everyone who cares, without the publisher ever needing to know who they are. That one property gives you decoupling, independent evolution, and a clean way to let one event ripple through a whole estate of systems.
The judgement, as always, is knowing when it fits. Use pub/sub when an event has many interested consumers and you want them to grow independently of the source. Reach for a queue when you are distributing work to one logical consumer, and for a synchronous API when a caller needs an immediate answer. Design every subscriber to be idempotent, plan for duplicates and out-of-order delivery honestly, and give yourself a dead-letter path for the messages that go wrong. Do that and pub/sub becomes one of the most dependable tools in your integration kit, sitting comfortably alongside the other patterns in the enterprise integration pillar.
Designing an event-driven integration?
Independent, vendor-neutral advice on messaging architecture, pub/sub and event-driven design, queue versus topic decisions, and connecting ERP, EAM and CAFM systems reliably. 22+ years across enterprise integration in utilities, oil and gas, manufacturing, government and facility operations.
Book a conversationRelated reading: Enterprise system integration explained, What is a message queue, What is event streaming, API vs webhook, Business Central APIs and integrations.
Muhammad Abbas
CMMS / CAFM Manager & Enterprise Integration Specialist · 22+ years across ERP, EAM, CAFM and enterprise integration.
Work with me