Compile Ready
Module 13 · JavaScript Design Patterns

The Publish/Subscribe Pattern

Intermediate12m read16m practice28m total
Design PatternsPub/SubEvent BusDecoupling

Introduction

The Publish/Subscribe Pattern routes messages through an intermediary broker, often called an event bus. Publishers send messages to topic strings; subscribers register handlers for topics. Publishers and subscribers do not need direct references to each other.

This pattern is interview-famous because it is simple to implement, easy to extend, and gives a clean comparison point against the Observer Pattern.

Why This Matters

Pub/Sub appears in front-end event buses, analytics pipelines, notification systems, WebSocket message routing, and distributed systems. In JavaScript interviews, candidates are often asked to implement subscribe, publish, and unsubscribe with correct handler order and cleanup.

Theory

Core idea

A broker stores a mapping from topic names to subscriber handlers. A publisher calls publish(topic, payload). The broker looks up handlers for that topic and invokes them with the payload.

Roles

  • Publisher: emits a message to a topic.
  • Subscriber: registers a handler for a topic.
  • Broker or event bus: stores topic subscriptions and dispatches messages.

Why it is more decoupled than Observer

In Observer, the subject owns observer references and directly calls observer.update(). In Pub/Sub, the publisher only knows a topic name and the broker. Subscribers also only know the broker and topic name. This means publishers and subscribers can be added, removed, tested, or moved independently.

Costs of loose coupling

Loose coupling can make flow harder to debug. Topic strings can be misspelled, event payload contracts can drift, and it may be unclear who is listening. Production systems often add constants, typed events, logging, or schema validation to reduce those risks.

Interview implementation checklist

A solid Pub/Sub implementation should:

  1. store handlers per topic,
  2. return an unsubscribe function from subscribe(),
  3. preserve subscription order during publish(),
  4. copy the handler list before publishing so unsubscription during delivery is safe,
  5. handle topics with no subscribers gracefully.

Visual Diagrams

Pub/Sub with an event broker
Publisher A
    |
    v
publish topic order.created
    |
    v
Event broker
    |
    +--> subscriber 1 for order.created
    +--> subscriber 2 for order.created

Publisher and subscribers do not reference each other directly

The broker is the intermediary that decouples message producers from message consumers.

Code Examples

Minimal event bus

A topic map stores handlers by event name. subscribe() returns an unsubscribe function.

Loading…

Same topic, multiple subscribers

The publisher does not know whether there are zero, one, or many subscribers.

Loading…

Playground

Loading editor…
Console

Press Run to execute the code and see output here.

Output Prediction

Predict the output #1

javascript
1function createBus() {
2 const topics = {};
3
4 return {
5 subscribe: function (topic, handler) {
6 if (!topics[topic]) {
7 topics[topic] = [];
8 }
9
10 topics[topic].push(handler);
11
12 return function () {
13 const index = topics[topic].indexOf(handler);
14 if (index !== -1) {
15 topics[topic].splice(index, 1);
16 }
17 };
18 },
19 publish: function (topic, payload) {
20 const handlers = topics[topic] || [];
21 handlers.slice().forEach(function (handler) {
22 handler(payload);
23 });
24 }
25 };
26}
27
28const bus = createBus();
29
30bus.subscribe('score', function (value) {
31 console.log('first:' + value);
32});
33
34const stopSecond = bus.subscribe('score', function (value) {
35 console.log('second:' + value);
36});
37
38bus.publish('score', 10);
39stopSecond();
40bus.publish('score', 20);

Coding Exercises

Implement a topic-based Pub/Sub broker

Medium

Implement createPubSub() with subscribe(topic, handler) and publish(topic, payload). subscribe() must return an unsubscribe function. publish() should call handlers for that topic in subscription order and do nothing for unknown topics.

Interview Questions

1Implement Publish/Subscribe and explain how it differs from Observer.

Pub/Sub stores handlers in a broker keyed by topic names. subscribe(topic, handler) registers a handler and returns an unsubscribe function; publish(topic, payload) asks the broker to invoke handlers for that topic. Observer is more direct: a subject stores observer objects and calls update() on them. Pub/Sub adds an intermediary, so publishers and subscribers are more loosely coupled and can communicate many-to-many through topics.

Asked at:NetflixMetaAmazon

Follow-ups

  • How would you avoid typo-prone topic strings?
  • How should errors in one subscriber affect the others?
2What are the disadvantages of Pub/Sub?

The same decoupling that makes Pub/Sub flexible can make it hard to debug. Event flow is indirect, topic names can drift, payload contracts can become unclear, and unused subscriptions can leak memory. Strong systems add naming constants, schemas or TypeScript types, logging, and disciplined cleanup.

Quiz

1. What extra component does Pub/Sub add compared with Observer?

2. Why should `publish()` iterate over a copy of the handler list?

Summary

  • Pub/Sub uses a broker that maps topic strings to subscriber handlers.
  • Publishers and subscribers do not reference each other directly.
  • `subscribe()` should return an unsubscribe function to prevent leaks.
  • Compared with Observer, Pub/Sub is more decoupled but can be harder to trace and validate.

Cheat Sheet

Roles: publisher emits, subscriber handles, broker routes.

Core methods: subscribe(topic, handler), publish(topic, payload), unsubscribe callback.

Data structure: topic name -> handlers array.

Observer vs Pub/Sub: Observer = subject directly calls observers. Pub/Sub = broker + topic strings + looser coupling.

Risks: typo-prone topics, hidden flow, payload drift, forgotten unsubscriptions.