ProgramGuru

Publisher/Subscriber Pattern

Publisher/Subscriber: start from the problem

See the responsibilities

PublisherAnnounces a committed fact
Topic or exchangeRoutes under a messaging contract
SubscriptionsTrack independent work
WorkersShare a subscription’s processing
Publisher: Announces a committed fact → Topic or exchange: Routes under a messaging contract → Subscriptions: Track independent work → Workers: Share a subscription’s processing

An accepted order needs notifications and analytics. Those consumers should receive their own opportunity to process the fact, while extra workers within notifications should share notification work rather than all send the same email.

This is a data and messaging pattern lesson. Follow the responsibilities, inspect the small JavaScript example and compare the design choices. The example is local teaching code; its boundary is explained before you apply the idea to a real service.

What you’ll learn

  • Explain the problem Publisher/Subscriber addresses and the roles involved.
  • Follow the example and distinguish this pattern from nearby alternatives.
  • Choose when the benefit justifies the extra responsibilities and testing.

How the responsibilities work

Publish/Subscribe separates publication from independent subscriptions. A messaging service can route one fact to each subscription; consumers within one configured group can compete for that group’s work. The chosen broker determines retention, delivery and ordering.

The local code below demonstrates two interested consumers, not a durable broker. It calls each function once in one process. Real subscribers need identities, progress and a duplicate-safe effect rule.

Follow a small example

Read the JavaScript from top to bottom and compare the expected output. The values are chosen to make this pattern’s responsibility visible. This example runs in one local execution context; it does not create remote services, durable storage or production access controls.

JavaScript · local teaching example

const subscribers = [
  event => 'notify ' + event.orderId,
  event => 'analyse ' + event.orderId
];
const event = {id: 'E1', orderId: 'O7'};
for (const subscriber of subscribers) console.log(subscriber(event));

Expected output

notify O7
analyse O7

Choose a design and inspect the consequence

Compare the design choices

Analytics is temporarily slow.
Three notification workers join one consumer group.

Compare the visible consequences. With JavaScript enabled, choose an option in each scenario to assemble your decision record.

This is an exploratory design exercise. It does not run infrastructure, measure capacity or replace the lesson’s quiz.

Use the consequences to explain your decision, including the simpler alternative.

Apply the pattern to two situations. Select one option in each situation to build a decision record. Every option and its consequence stays visible, and you can change your choices.

When it helps—and what it costs

Use it when several independent consumers need a fact and the publisher should not wait for each business action to finish. Define whether publication or actual business completion is the acknowledged outcome.

Slow subscriptions, retention expiry, duplicate delivery and schema changes need recovery rules. A shared work queue is not the same as independent subscriptions. Do not promise all consumers instantly see a transaction because an event was published.

Distinguish the neighbouring patterns

Observer often describes local callbacks. Outbox addresses the source-commit/publication gap. Event Sourcing concerns authoritative history rather than merely topic delivery.

Follow local notification lifetimes, worker groups and subscription recovery, commit-to-publication safety to compare the specific responsibility before combining patterns.

For further reading, use Microsoft’s Publisher/Subscriber guidance. Compare it with this original example and the guarantee required by your application.

Check your pattern reasoning

Why give analytics a separate subscription from notifications?
Choose one answer. You can try again.

Answer and explanation

Each capability needs its own processing progress.

Independent consumers must not merely compete for one shared job.

Check your pattern reasoning

Does pub/sub itself guarantee no repeated emails?
Choose one answer. You can try again.

Answer and explanation

No; consumer effects need a duplicate-handling contract.

Broker delivery and external effects have different boundaries.

Name the responsibility before choosing the pattern

For Publisher/Subscriber, describe the problem, the participating roles and the observable contract. Use the example as a starting point and test the boundaries identified in the trade-offs. A pattern name alone does not establish correctness or performance.

Return to the design-pattern guide to compare families, or apply the idea alongside commit-to-publication safety.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Transactional Outbox Pattern →