Pub/Sub Architecture
Publish-subscribe (pub/sub) is a messaging pattern in which publishers send messages to a named channel or topic without any knowledge of who, if anyone, is listening, and subscribers express interest in a topic without any knowledge of who is publishing to it. This is a fundamentally different relationship than a direct queue between one producer and one consumer: pub/sub is built for fan-out, where a single event may need to reach zero, one, or many independent subscribers, and new subscribers can be added later without changing the publisher at all. This decoupling in both direction (who) and cardinality (how many) is what makes pub/sub the natural backbone for event-driven architectures, where many independently-deployed services all want to react to the same underlying business events.
Cricket analogy: A stadium's PA broadcasts the 'wicket fallen' announcement to everyone in earshot without knowing who's listening, the scoreboard, broadcast truck, and fans' radios all pick it up independently, and a new food vendor's screen can start listening tomorrow without the PA changing.
Topics, Subscriptions, and Fan-Out
In most pub/sub systems (Google Cloud Pub/Sub, AWS SNS, or Kafka topics with multiple consumer groups), a publisher writes a message to a topic, and the messaging system fans that single message out to every active subscription on that topic — each subscription gets its own independent copy or offset into the stream, so one subscriber being slow or behind does not affect any other subscriber. This is distinct from a plain queue's competing-consumers model, where multiple consumers reading the same queue split the work among themselves rather than each receiving every message. Pub/sub systems often layer filtering on top of fan-out, letting subscribers specify attributes or patterns (e.g., 'only orders over $100' or 'only events from region=EU') so they receive a relevant subset of a topic's traffic rather than the full firehose. A common design mistake is relying purely on this client-side filtering against one undifferentiated topic, since it wastes bandwidth and couples every subscriber to a single evolving schema; it's usually better to define separate topics around meaningful, versioned business events (e.g., 'order.placed' vs. 'order.cancelled') so subscribers can select at the topic level and schema changes don't silently break unrelated consumers.
Cricket analogy: When a 'six hit' event fans out, the scoreboard, broadcast graphics, and a stats app each get their own independent copy so a slow stats update doesn't delay the scoreboard, and the league defines separate topics like 'boundary.six' versus 'boundary.four' rather than one filtered firehose.
Push vs. Pull Delivery
Pub/sub subscribers can receive messages via push, where the messaging system actively calls a subscriber's endpoint (e.g., an HTTP webhook) as messages arrive, or pull, where the subscriber's own process actively polls the system for new messages when it's ready to handle them. Push delivery minimizes latency and simplifies the subscriber (no polling loop needed) but requires the subscriber to expose a reachable endpoint and to handle backpressure carefully, since the publisher-side system controls the delivery rate. Pull delivery puts the consumer in control of its own processing rate, which is usually preferable for high-throughput or batch-oriented consumers that want to control concurrency and avoid being overwhelmed by a push-based flood, at the cost of slightly higher latency and the operational overhead of running a polling consumer process.
Cricket analogy: A stadium's push-alert system buzzes fans' phones the instant a wicket falls, minimizing delay but requiring every phone to be reachable; a scorecard app fans manually refresh is pull-based, trading immediacy for control.
Pub/sub fan-out on a single topic 'order.placed':
[Order Service] --publish--> [Topic: order.placed]
|
+------------------------+------------------------+
| | |
[Subscription: Inventory] [Subscription: Email] [Subscription: Analytics]
(own offset/ack state) (own offset/ack state) (own offset/ack state)
Each subscription independently tracks its own progress; a slow
Analytics consumer does not delay or block the Inventory or Email
subscriptions from processing the same published message.Slack's internal architecture uses pub/sub extensively: when a message is posted in a channel, that single event fans out to dozens of independent subscribers — the search indexer, notification service, unfurl/preview service, compliance/export pipeline, and real-time WebSocket fan-out to connected clients — each added over time without ever requiring a change to the original 'message posted' publisher, which is the essential value proposition of decoupling producers from an evolving set of consumers.
Ordering and At-Least-Once Semantics
Most pub/sub systems provide at-least-once delivery per subscription and make no strong ordering guarantee across an entire topic by default, especially once a topic is partitioned or sharded for scale — messages published close together in time may be delivered to a given subscriber out of order, and the same message may be redelivered if an acknowledgment is lost. Systems that need ordering (e.g., Kafka, or Google Cloud Pub/Sub's ordering keys) typically only guarantee order within a partition or ordering key, meaning you must deliberately route causally related messages (e.g., all events for the same order ID) to the same partition/key if you need them processed in order, while accepting no cross-key ordering guarantee.
Cricket analogy: A broadcast feed guarantees each commentary box gets every update at least once but makes no promise that updates from two simultaneous grounds arrive in sync, only updates within the same match's feed, its partition, are guaranteed in order.
- Pub/sub decouples publishers from subscribers in both identity and cardinality, enabling one event to fan out to many independent consumers.
- Each subscription tracks its own delivery/acknowledgment state, so a slow subscriber does not block or delay other subscribers.
- Push delivery minimizes latency but requires a reachable subscriber endpoint; pull delivery gives the subscriber control over its own processing rate.
- Well-designed topics map to meaningful, versioned business events rather than a single catch-all channel with client-side filtering.
- Pub/sub systems typically guarantee at-least-once delivery with no strong cross-topic ordering; ordering, if needed, is usually scoped to a partition or key.
- Pub/sub is the natural backbone for event-driven architectures, allowing new consumers to be added without modifying the publisher.
Practice what you learned
1. What fundamentally distinguishes pub/sub from a traditional point-to-point message queue?
2. What is the main tradeoff of push-based delivery compared to pull-based delivery in a pub/sub system?
3. How do most pub/sub systems handle message ordering across an entire topic by default?
4. Why is defining topics around well-scoped, versioned business events generally better than one catch-all topic with client-side filtering?
5. Why does adding a new subscriber to an existing pub/sub topic typically not require changing the publisher?
Was this page helpful?
You May Also Like
Message Queues Explained
Message queues decouple producers from consumers by buffering work as discrete messages, enabling asynchronous processing, load leveling, and resilience to downstream slowdowns.
Event-Driven Architecture
A design style where services communicate by producing and reacting to events rather than calling each other directly, enabling loose coupling and independent scaling.
Idempotency in Distributed Systems
The property that performing the same operation multiple times produces the same result as performing it once, essential for safely retrying requests over unreliable networks.
Consistency Models
Consistency models define the contract about what values reads may return after concurrent writes, ranging from strict linearizability to loosely-ordered eventual consistency.
Related Reading
Related Study Notes in Software Engineering
Browse all study notesMicroservices Study Notes
Software Architecture · 30 topics
Software EngineeringTesting & TDD Study Notes
Software Testing · 30 topics
Software EngineeringDesign Patterns Study Notes
Software Design · 30 topics
Software EngineeringSoftware Engineering Study Notes
Python · 40 topics
Software EngineeringGit & Version Control Study Notes
Bash · 40 topics