Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

System Design (High-Level Design)  Module 19 – Building blocks: traffic, storage and messaging

Design a pub-sub system with fan-out

Design a publish-subscribe service with topics and subscriptions, push or pull delivery, ack deadlines, ordering keys, filters and dead letters.

  • Intermediate
  • 30 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0 and quickjs 0.32.0
  • By MySmartCoPilot
Free intro, Pro: 5 of 30 minutes free
Free: Fan-out turns 50 MB a second of publishing into 500 MB of delivery. With a pass: the other 15 sections and 3 interview answers, about 25 minutes.

What you will learn

  • Estimate the deliveries, bandwidth and storage of a pub-sub service from its fan-out
  • Design topics, subscriptions and message storage for many subscribers per topic
  • Choose push or pull delivery and acknowledgement deadlines for each subscriber
  • Order messages per key with ordering keys, filter at the service, and route poison messages to dead letters
  • Plan for subscribers that fall behind, fail or disappear for days

Before you start

What you’ll learn · Before you start

What you will learn

  • Estimate the deliveries, bandwidth and storage of a pub-sub service from its fan-out
  • Design topics, subscriptions and message storage for many subscribers per topic
  • Choose push or pull delivery and acknowledgement deadlines for each subscriber
  • Order messages per key with ordering keys, filter at the service, and route poison messages to dead letters
  • Plan for subscribers that fall behind, fail or disappear for days

Before you start

On this page

An “order placed” event on a company’s event platform must reach billing, email, search, analytics and 30 other services, and the busiest topic already has 300 subscriptions. A publish-subscribe: A messaging style in which a producer publishes an event and every subscriber receives its own copy and acts on it in its own time, without the producer knowing who listens. More in “Synchronous vs asynchronous communication” service lets the publisher send each message once and delivers a copy to every subscription, so the publisher never needs to know who is listening.

Each subscription tracks what its subscribers have acknowledged and delivers the rest again, by letting workers pull or by pushing to an endpoint. You will estimate what fan-out does to bandwidth and storage, step one event through a first design, and then work out where messages live, how long a subscriber may hold one, how ordering keys fence off a slow key, and what happens to a subscriber that disappears for days.

Fan-out turns 50 MB a second of publishing into 500 MB of delivery

Rates, fan-out, delivery and retention each change the design, so ask about them first. This platform’s answers:

The question to ask This platform’s answer
How many messages a second, and how large? 50,000 at peak and 20,000 on average, 1 KB each
How many subscriptions per topic? 10 on average, 300 on the busiest topic
Do subscribers pull, or must the service call their HTTPS endpoints? Both
Must related messages arrive in order? Yes, per key, such as per order
Delivered at least once, or more strictly? At least once
How long may a subscriber be away, and may it replay old messages? Messages are kept 7 days for replay

Functional requirements: create topics and subscriptions; publish batches; pull, acknowledge and extend deadlines; push to endpoints with retries; ordering keys; filters; dead-letter topics; replay from a time. Non-functional requirements: no message lost once publish succeeds, delivery within about 100 ms for healthy subscribers, and a slow subscriber never slows the publisher or other subscribers.

The first estimate multiplies those answers:

Deliveries, bandwidth and storage for the fan-out Python · plan/fanout_estimate.py
# A first estimate for the pub-sub service of this lesson. The inputs are assumptions to replace with measurements.
PEAK_PUBLISH, AVG_PUBLISH = 50_000, 20_000   # messages published a second, across all topics
MSG_BYTES = 1_000
FAN_OUT = 10                                 # subscriptions per topic, on average
RETENTION_DAYS, COPIES = 7, 3                # kept for replay, and replicated three times
MB, TB = 10**6, 10**12

kept = AVG_PUBLISH * MSG_BYTES * RETENTION_DAYS * 86_400 * COPIES
print(f"publish at peak: {PEAK_PUBLISH:,} messages/s × {MSG_BYTES:,} bytes = {PEAK_PUBLISH * MSG_BYTES / MB:,.0f} MB/s in")
print(f"deliveries at peak with an average fan-out of {FAN_OUT}: {PEAK_PUBLISH * FAN_OUT:,} messages/s, "
      f"{PEAK_PUBLISH * FAN_OUT * MSG_BYTES / MB:,.0f} MB/s out")
print(f"{RETENTION_DAYS} days kept for replay, {COPIES} copies: one shared log {kept / TB:,.1f} TB; "
      f"a copy for every subscription {kept * FAN_OUT / TB:,.0f} TB")

Output

publish at peak: 50,000 messages/s × 1,000 bytes = 50 MB/s in
deliveries at peak with an average fan-out of 10: 500,000 messages/s, 500 MB/s out
7 days kept for replay, 3 copies: one shared log 36.3 TB; a copy for every subscription 363 TB

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 fanout_estimate.py

Fan-out multiplies everything that happens after the publish: 50 MB a second in becomes 500,000 deliveries and 500 MB a second out. Storage depends on where messages live: 36.3 TB for one shared log, ten times as much if every subscription keeps its own copy.

Checkpoint

Check the estimate

  1. Question 1 of 3 If the average fan-out were 25 subscriptions instead of 10, how many deliveries a second would the 50,000-message peak need?

    Type a number.

    A hint

    Every subscription receives its own copy of every message.

    Show the answer: Question 1 of 3

    Answer: 1250000 deliveries a second (anything from 1125000 to 1375000 counts)

    Every published message is delivered once per subscription: 50,000 × 25 = 1,250,000 deliveries a second, and at 1 KB each, about 1.25 GB a second out. The bytes published stay at 50 MB a second.

  2. Question 2 of 3 Keep messages 14 days for replay instead of 7, at 20,000 messages a second of 1 KB with 3 copies. About how many TB does one shared log hold?

    Type a number.

    A hint

    Bytes a second, times the seconds in 14 days, times the replicas.

    Show the answer: Question 2 of 3

    Answer: 72.6 TB (anything from 65.3 to 79.9 counts)

    20,000 × 1,000 bytes = 20 MB a second; 14 days are 1,209,600 seconds, so one copy is about 24.2 TB and three copies about 72.6 TB, twice the 36.3 TB of the 7-day estimate.

  3. Question 3 of 3 Keep the same 14 days, but let every one of the 10 subscriptions keep its own copy instead of one shared log. About how many TB is that?

    Type a number.

    A hint

    Copies multiply the shared log by the number of subscriptions.

    Show the answer: Question 3 of 3

    Answer: 726 TB (anything from 653 to 799 counts)

    Copies multiply storage by the fan-out: 72.6 TB × 10 = 726 TB.

The first design: one log per topic, a small state per subscription

Publishers write each message once to the topic’s log. Each subscription reads the log from its own cursor and hands messages out under a lease, pull and push dispatchers deliver them, and messages that fail too often go to a dead-letter topic.

Publishers write each message once to a topic log; subscriptions keep cursors and leases; pull and push delivery; a dead-letter topic.Publishersservices sending events to a topicPublish APIauthenticate, validate, batch;reply once the message is storedTopic storageone partitioned, replicated log per topic;each message stored onceSubscriptionsDeliveryDead-letter topicmessages that failed too oftenSubscription: billingcursor · leases · filterSubscription: emailcursor · leases · ordering keysPull APIworkers ask for messagesand acknowledge themPush dispatchersPOST to an endpoint,retry with backoffpublish(topic, messages)appendread from each cursorlease a message until its deadlineafter the last attempt

The first design of the pub-sub service

Text description of the diagram

The diagram shows the first design from top to bottom.

  • Publishers, the services that send events, call publish with a topic and a batch of messages.
  • The publish API authenticates and validates the request, batches messages, and replies only once each message is stored.
  • Topic storage keeps one partitioned, replicated log per topic, so each message is stored once however many subscriptions read it.
  • Each subscription, such as billing or email, reads the log from its own cursor and keeps its leases: which messages are out to a subscriber and until when. A subscription may also have a filter or use ordering keys.
  • Delivery happens in two ways: a pull API, where workers ask for messages and acknowledge them, and push dispatchers, which send each message to an endpoint with an HTTP POST and retry with backoff.
  • A dashed arrow leads from delivery to a dead-letter topic, which receives messages after their last failed attempt.

Step one event through it, from the publish to both acknowledgements:

Interactive · step by step One event through the first design, from publish to two acknowledgements Step through one order event as the service stores it once and delivers a copy to each of two subscriptions.
One event through the first design, from publish to two acknowledgements, step 9 of 9. Showing Order service, Publish API, Topic log (orders, event stored), Billing subscription (pull, done), Email subscription (push, done), Billing workers, Email endpoint.Order servicethe publisherPublish APITopic logorders, event storedBilling subscriptionpull, doneEmail subscriptionpush, doneBilling workersEmail endpointHTTPS200 OK

The drawing shows the whole scene; its 9 steps are listed below.

Every step as text
  1. Publish once. The order service publishes an "order placed" event to the orders topic. It sends the event once, whoever subscribes to it.
  2. Stored once. The publish API appends the event to the topic's log, which keeps it on several replicas. It is stored once, however many subscriptions read it.
  3. A reply after storing. Only once the event is stored does the API return its message ID. From then on, the service must not lose it.
  4. Every subscription sees it. Billing and email each have a subscription to the topic. Each reads the log from its own cursor, so the event is now waiting for both.
  5. Billing pulls. A billing worker asks for messages when it is ready and receives the event with a lease, an acknowledgement deadline after which the event would be delivered again.
  6. Billing acknowledges. The worker records the payment and acknowledges the event. The billing subscription will not deliver it again, and its cursor can move past it.
  7. Email is pushed. The email subscription sends the event to the email service's HTTPS endpoint. A success status in the reply is the acknowledgement.
  8. A failure stays apart. The endpoint answers with an error, so the email subscription keeps the event and retries later. Billing is not slowed, because each subscription has its own cursor and leases.
  9. Two deliveries. The endpoint answers 200 on the retry, and the event is done for both. One publish became two deliveries, a fan-out of 2; this platform averages 10, and its busiest topic has 300.

Six choices are still open, each in one sentence:

  • A shared log with cursors: each message is stored once, and every subscription records how far it has read.
  • A copy per subscription: each subscription keeps its own queue of the messages it has not acknowledged.
  • Pull or push: workers ask for messages when they are ready, or the service sends each message to an endpoint.
  • Acknowledgement deadlines: how long a delivered message may stay unacknowledged before it is delivered again.
  • Ordering keys: messages with the same key reach a subscription in the order they were published.
  • Filters and dead-letter topics: a filter passes only messages whose attributes match, and a dead-letter topic takes messages that failed too often.

The deep dives that decide whether the design works:

  1. Where are messages stored when one topic has 300 subscriptions, and what does each subscription keep?
  2. How long should an acknowledgement deadline be, and what happens when work takes longer?
  3. When should delivery be push, and when pull?
  4. How do ordering keys keep order without letting one slow key stall everything?
  5. Where do filters run, and what do they do to cost and backlog?
  6. What happens to a message that always fails, and to a subscriber that is away for two days?

An answer is judged on requirements and estimates, storage and fan-out, delivery and acknowledgement, ordering, failure handling and operations.

Checkpoint

Check the first design

  1. Question 1 of 2 Which delivery mode lets the subscriber's own workers decide how fast they receive messages?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Pull delivery, because workers ask for messages when they are ready

    With pull, a worker requests messages only when it can handle them. With push, the service decides when to send, so the endpoint must keep up or answer with errors.

  2. Question 2 of 2 A billing worker pulls the "order placed" event and crashes before it acknowledges it. What does the billing subscription do?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: It delivers the event again once the acknowledgement deadline has passed

    A delivered message is leased until its acknowledgement deadline. When the deadline passes with no acknowledgement, the subscription delivers the message again; the email subscription is not affected at all.

A subscription is a cursor, the acknowledgements above it and a lease table Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • One shared log keeps storage flat as fan-out grows
  • Delivery is a lease, and a deadline shorter than the work runs a message twice
  • Pull lets the subscriber set the pace; push needs only an endpoint
  • Ordering keys keep order per key and fence off a slow key
  • Filters at the service spare every subscriber the unwanted messages
  • A poison message needs an attempt limit, a dead-letter topic and a way back
  • A subscriber away for two days loses time, not messages
    • Two days away
    • An endpoint that fails for an hour
    • A storage node that dies
  • At 10×, delivery is the bottleneck; at 100×, the number of subscriptions is
  • Alternatives rejected
  • What each level is expected to cover
  • A sample answer and a 45-minute self-mock
  • Practise: dispatch in order per key
    • Dispatch messages in order per key, in parallel across keys
  • Interview questions
    • One topic receives 20,000 messages a second of 1 KB and has 300 subscriptions, and each subscription must be able to replay the last 7 days. Your first design keeps a queue per subscription. Estimate its storage and write load, and propose a better design with its trade-offs.
    • A billing subscriber pulls "order paid" events with a 10-second acknowledgement deadline. On busy days some customers are charged twice, and the duplicates line up with charges that took more than 10 seconds. Explain the mechanism and fix it on both the subscription and the subscriber side.
    • A subscription uses ordering keys set to the merchant ID. One large merchant's events now arrive minutes late, and once a malformed event stopped that merchant's events for an hour. Every other merchant is fine. Explain both problems and redesign the keys and the failure handling.
  • Key takeaways

3 diagrams · 3 runnable examples (JavaScript, Python) · 1 exercise with sample tests · 3 interview answers · about 61 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Read a complete sample first: Design a unique ID generator

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.