Decouple producers from consumers through a broker and topics, so a publisher never needs to know who's listening.
An `OrderPlaced` event might need to reach inventory, billing, analytics, and email — today. If the order service calls each of those directly, adding a fifth interested service next quarter means changing the order service's code again, even though the order service itself hasn't changed.
Publishers send messages to a named topic on a broker, with no knowledge of who's subscribed. Any number of subscribers can register interest in that topic and each independently receives a copy of every message — subscribers can be added or removed without touching the publisher at all.
`orders.publish(...)` doesn't know or care that three subscribers exist — adding a fourth is one `subscribe` call, with zero changes to the publisher.
class Broker {
#topics = new Map();
subscribe(topic, handler) {
if (!this.#topics.has(topic)) this.#topics.set(topic, new Set());
this.#topics.get(topic).add(handler);
}
publish(topic, message) {
for (const handler of this.#topics.get(topic) ?? []) {
handler(message);
}
}
}
const broker = new Broker();
broker.subscribe("OrderPlaced", (order) => console.log(`billing: charge for ${order.id}`));
broker.subscribe("OrderPlaced", (order) => console.log(`analytics: logged ${order.id}`));
broker.subscribe("OrderPlaced", (order) => console.log(`email: confirmation for ${order.id}`));
// OrderService only ever does this — it has no idea who's listening:
broker.publish("OrderPlaced", { id: "order-42" });