Publish-Subscribe Pattern

A messaging pattern where a publisher broadcasts events to a topic or channel and multiple independent subscribers each receive a copy, without the publisher knowing who (or how many) subscribers exist.

Problem

Multiple services need to react to the same event (e.g., an order placed triggers inventory update, email notification, and analytics pipeline). Directly calling each service couples the event source to every downstream consumer and requires changes every time a subscriber is added or removed.

Solution / Explanation

The publisher sends messages to a topic (or fanout exchange). The messaging infrastructure routes a copy of each message to every registered subscriber’s queue. Publishers and subscribers are fully decoupled: neither knows the other’s identity or count.

Topics vs. Queues

Queue (Point-to-Point)Topic (Publish-Subscribe)
ReceiversOne consumer per messageAll subscribers get a copy
Competing consumersYes — load-balancedNo — each subscriber is independent
Use caseTask distributionEvent fan-out

In AMQP (RabbitMQ)

A fanout exchange broadcasts every message to all bound queues. Each subscriber declares its own queue and binds it to the exchange. A topic exchange adds selective subscription via routing-key patterns (e.g., order.*.created matches any region).

In Kafka

Kafka models pub-sub through consumer groups. Multiple consumer groups can read the same topic independently, each maintaining their own offset. Within a consumer group, partitions are distributed among members for parallel processing. See Apache Kafka for detail.

Difference from Observer Pattern

The Observer pattern (GoF) operates in-process: subject and observers share the same runtime, and notification is synchronous. Pub-sub is distributed: publisher and subscribers run in separate processes (often separate services), communication is asynchronous, and the broker guarantees delivery even if a subscriber is temporarily offline (durable subscribers).

ObserverPublish-Subscribe
ScopeIn-processDistributed / cross-service
CouplingSubject knows observer interfaceNo direct coupling
DeliverySynchronousAsynchronous
DurabilityLost if observer is unavailableDurable when queue is persistent

Key Components

  • Publisher — produces events without knowledge of consumers.
  • Topic / Exchange — the named channel events are published to.
  • Subscription / Binding — the link between a topic and a subscriber’s queue.
  • Subscriber — receives events and reacts independently.
  • Durable Subscriber — retains messages while offline (EIP pattern).

When to Use

  • Multiple independent services must react to the same domain event (order created, user registered).
  • Fan-out notifications (push to mobile devices, webhooks).
  • Decoupling an event source from a variable number of downstream consumers.
  • Audit logs, analytics pipelines, and caches that shadow domain events.

Trade-offs

BenefitCost
Publisher/subscriber fully decoupledNo delivery confirmation back to publisher
Easy to add new subscribersMessage duplication possible; consumers must be idempotent
Each subscriber processes independentlyFan-out amplifies load on the broker
Supports slow/fast subscribers independentlyOrdering only guaranteed per-partition/queue