{"post":{"slug":"what-is-a-publish-subscribe-pattern-2026","title":"Publish-Subscribe Pattern Explained in 2026","excerpt":"Publish-subscribe decouples senders from receivers through a topic instead of a direct address, and the same pattern shows up from a browser event listener to a Kafka cluster. Here is what it actually is in 2026.","category":"code","date":"July 20, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">P</span>ublish-subscribe, usually shortened to pub/sub, is a messaging pattern where senders (publishers) broadcast to a named channel (a topic) without knowing who, if anyone, is listening, and receivers (subscribers) register interest in a topic without knowing who publishes to it. Neither side holds a reference to the other. That single design choice — routing through a topic instead of a direct address — is what lets the same idea scale from a single function call inside one process to a cluster handling millions of events a second.\n\n## What changed in 2026\n\n- **Serverless pub/sub became the default for small teams.** Cloudflare Queues, Supabase Realtime, and similar managed primitives let teams add topic-based messaging without standing up a broker.\n- **Browser-native options matured.** BroadcastChannel and Server-Sent Events now cover many cross-tab and simple real-time cases that used to reach straight for a full WebSocket setup.\n- **Multi-agent AI systems adopted pub/sub for coordination.** Frameworks running several AI agents concurrently increasingly use an internal event bus so agents react to each other without being wired together directly.\n\n## Publisher, subscriber, topic\n\nA publisher sends a message tagged with a topic and moves on; it does not wait for anyone to read it. A subscriber registers interest in a topic and receives every message published to it from then on. The topic is the only thing connecting them — swap out every subscriber, add ten more, or remove them all, and the code on the publisher side does not change.\n\nThis produces decoupling along two axes that matter: neither side needs the other address or identity, and a publisher does not block waiting for a subscriber to finish — a natural fit for anything that should not slow down the sender.\n\n## Where the pattern shows up\n\nPub/sub is not one technology; it is a shape that recurs at every layer of a system.\n\n| Layer | Example technology | Delivery scope |\n| --- | --- | --- |\n| In-process | EventEmitter, signals, RxJS Subjects | Same process only |\n| Browser | DOM events, BroadcastChannel, SSE | Same tab or same-origin tabs |\n| Real-time app | WebSocket fan-out, Redis Pub/Sub, Pusher-style services | Currently connected clients |\n| Mobile push | FCM topics, APNs topics | Subscribed devices, queued while offline |\n| Backend infra | Kafka topics, Google Pub/Sub, AWS SNS, MQTT | Cross-service, often durable |\n\nThe properties change a lot down that table — an in-process emitter has zero persistence; a Kafka topic can retain messages for days and replay them to a brand-new subscriber. What stays constant is the shape.\n\n## Pub/sub versus the alternatives\n\nA point-to-point queue delivers each message to exactly one consumer, for distributing work, not broadcasting an event. A direct API call or RPC expects a reply and couples the caller to a specific address, which pub/sub deliberately avoids. The [observer pattern](/blog/observer-pattern-explained-2026) is the closest relative, but classic observer usually has the subject holding direct references to its observers, while pub/sub routes through an intermediary so the two sides often never know about each other at all. When that intermediary becomes real infrastructure, you are looking at a [message broker](/blog/what-is-a-message-broker-2026).\n\n## A minimal implementation\n\nThe core idea fits in a few lines, backed by nothing more than an array:\n\n```js\nclass Topic {\n  subscribers = [];\n  subscribe(fn) { this.subscribers.push(fn); }\n  publish(message) { this.subscribers.forEach(fn => fn(message)); }\n}\n\nconst orders = new Topic();\norders.subscribe(order => sendReceipt(order));\norders.subscribe(order => updateInventory(order));\norders.publish({ id: 42, total: 19.99 });\n```\n\nRedis gives the same shape across processes with two commands: `SUBSCRIBE orders` and `PUBLISH orders '{\"id\": 42}'`. Neither example has persistence, replay, or delivery guarantees — that is the honest baseline of pub/sub. Anything beyond that is a feature of the broker layered on top, not the pattern itself.\n\n## Common pitfalls\n\n- **Assuming delivery guarantees you do not have.** Plain pub/sub (an event emitter, browser events, basic Redis pub/sub) is fire-and-forget: if no subscriber is listening at publish time, the message is gone. Durable delivery and replay require a broker built for it, covered in more depth in [event-driven architecture](/blog/event-driven-architecture-2026).\n- **Topic sprawl with no ownership.** A topic per event type sounds clean until there are hundreds of them and no one can say who owns which. Name and document topics deliberately.\n- **Using pub/sub where a reply is actually needed.** If the publisher needs to know the outcome, it is describing a request-response interaction, not an event, and forcing it into pub/sub adds indirection without benefit.\n\n## FAQ\n\n**Is publish-subscribe the same as a message queue?**\nNo. A queue delivers each message to exactly one consumer, for splitting up work. Pub/sub delivers each message to every current subscriber, for broadcasting an event to however many interested parties exist.\n\n**Do I need a message broker to use publish-subscribe?**\nNo. Pub/sub is a pattern, not a product. An in-process event emitter is pub/sub. A broker is what you reach for once you need the pattern to work across services, processes, or machines, with durability guarantees.\n\n**Can a subscriber miss a message?**\nDepends on the implementation. Basic pub/sub (browser events, a plain event emitter, unbuffered Redis channels) delivers only to subscribers connected at publish time. Brokers with persistence and consumer offsets, like Kafka, let a subscriber catch up on messages published before it connected.\n\n**How is pub/sub different from webhooks?**\nA webhook is typically one publisher calling one known URL directly, closer to point-to-point than broadcast. Pub/sub decouples the publisher from knowing who or how many receivers exist at all.\n\n## Where to go next\n\n- [The observer pattern explained in 2026](/blog/observer-pattern-explained-2026)\n- [What is a message broker in 2026](/blog/what-is-a-message-broker-2026)\n- [Event-driven architecture in 2026](/blog/event-driven-architecture-2026)","hue":150,"metaTitle":"Publish-Subscribe Pattern Explained 2026","metaDescription":"What the publish-subscribe pattern actually is in 2026 — publishers, subscribers, and topics, where the pattern shows up, and when to skip it.","keywords":["publish-subscribe pattern 2026","pub sub pattern explained","publish subscribe vs observer pattern","topic based messaging","event emitter pattern","pub sub architecture explained","publish subscribe design pattern","decoupled messaging pattern"],"tldr":["**A publisher never addresses a subscriber directly** — both sides only know about a topic, which is what makes the pattern reusable at almost any scale.","**The same pattern runs at wildly different altitudes** — an in-process event emitter, a browser tab, and a Kafka cluster are all publish-subscribe underneath.","**Fire-and-forget is the default, not a flaw** — a publisher that needs a reply is describing a request, and needs a different pattern entirely.","**Topic design is the real skill** — too few topics and every subscriber filters noise; too many and nobody can find the one they need.","**Skip:** reaching for a message broker to implement pub/sub inside a single process — an event emitter or a signal already does the job with none of the operational cost."],"readTime":"4 min read","wordCount":950},"related":[{"slug":"observer-pattern-explained-2026","title":"The Observer Pattern Explained in 2026","excerpt":"Observer pattern lets objects subscribe to state changes in another object without tight coupling between them. Here is how it works in 2026 and where it shows up in everyday frameworks.","category":"code","date":"July 2, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":150},{"slug":"what-is-a-message-broker-2026","title":"What Is a Message Broker in 2026: A Practical Guide","excerpt":"Message brokers decouple services so they do not have to talk to each other directly. Here is how they work and how to choose between the major options.","category":"code","date":"July 7, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":320},{"slug":"message-brokers-deep-dive-explained-2026","title":"Message brokers deep dive in 2026: Kafka, RabbitMQ, and when to use each","excerpt":"Message brokers decouple services and enable async processing, but Kafka and RabbitMQ solve different problems. Here is the 2026 guide to picking the right one.","category":"code","date":"April 20, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":308}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"what-is-a-proxy-vote-2026","title":"What Is a Proxy Vote? A 2026 Shareholder Guide","excerpt":"A plain-language guide to proxy voting in 2026 — how shareholders vote on company matters without attending the annual meeting, and why most proxy votes go uncast.","category":"finance","date":"July 20, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":45},"older":{"slug":"what-is-a-pull-request-review-2026","title":"What Is a Pull Request Review in 2026?","excerpt":"A pull request review is the formal approve, comment, or request-changes decision attached to a pull request, not just the act of reading code. Here is how the review step actually works in 2026.","category":"code","date":"July 20, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":310}}