Publish / Subscribe
One new Adda post must ripple to the feed, search, notifications, and analytics. If the Posts service has to call each of them, it becomes everyone's bottleneck. Pub/sub lets it broadcast and forget.
The problem
A user publishes a post. That one fact needs to ripple everywhere: fan it into followers' feeds, index it for search, notify anyone mentioned, update the analytics dashboard, run it past moderation, award activity points. Today Adda's Posts service calls each of those services directly, one after another.
Every time the team adds a reaction — "also push a mobile alert," "also update the trending model" — someone edits the Posts service and redeploys it. Posts now imports and knows about eight other services. It's slow (it waits on all of them), fragile (if Notifications is down, the post itself fails), and the team that owns Posts has become a bottleneck for everyone who wants to react to a new post.
A first attempt
Push the calls onto a message queue so Posts doesn't block — the queue trick Adda just learned. Better: Posts enqueues a job and returns. But a plain queue is point-to-point: each message goes to exactly one consumer. To feed six different reactions you'd create six queues and have Posts write the same event into all six, one enqueue per consumer.
That's still Posts knowing its whole audience. Add a seventh reaction and Posts changes again. The coupling didn't go away — you just moved it. The producer is still responsible for knowing every consumer, which is exactly the knot you wanted to cut.
The insight
Flip who knows whom. Instead of the producer sending to N known consumers, the producer publishes one event to a named topic and forgets about it. Any service that cares subscribes to that topic and receives its own copy.
That's publish/subscribe. Posts publishes PostCreated once. Feed, Search, Notifications,
and Analytics each subscribe independently. Adding a new reaction means adding a new subscriber
— the producer never changes. Posts no longer knows or cares who's listening.
Pub/sub inverts the dependency
In direct calls, the producer depends on every consumer. In pub/sub, consumers depend on the event, not the producer. Producers and consumers evolve independently — the essence of event-driven architecture.
How it works
Producer publishes to a topic
Posts emits one message — PostCreated { postId, userId, body } — to the posts topic. It
doesn't know how many subscribers exist, or any of them. Publish and move on.
The broker fans out
The broker copies that event to every subscription attached to the topic. One publish becomes N deliveries — one per interested service — without the producer lifting a finger.
Each subscriber consumes independently
Feed, Search, and Analytics each have their own subscription and their own backlog. A slow subscriber builds up its own queue; it doesn't slow the others or the publisher. Each processes at its own pace.
Add reactions without touching the producer
Marketing wants a push alert on every post from someone you follow? They stand up a service and
subscribe to posts. The Posts service is never redeployed, never even told. The system grows
at the edges.
Concrete numbers
Fan-out is the headline: 1 publish → N deliveries. A busy topic on Kafka or Google Pub/Sub handles hundreds of thousands to millions of messages per second and delivers to each subscriber group in parallel, typically within tens of milliseconds end to end.
Compare the coupling cost directly. Direct calls to 6 services in sequence, each ~20 ms, make the post request wait ~120 ms and fail if any one is down. Publish to a topic and Posts waits ~2 ms for the broker ack and always succeeds regardless of a subscriber being down — that subscriber just processes its backlog once it recovers. You traded synchronous certainty for asynchronous resilience.
When to use it
Fan-out means no single 'it's done' moment
After Posts publishes, the search index may update in 50 ms and the notification may fire 3 s later. There's no instant where you can say "the whole post finished," because each subscriber runs on its own clock. If a step must complete before you respond to the user (like saving the post itself), keep that synchronous — publish only the reactions that are genuinely fire-and-forget.
Ordering and duplicates are still your problem
Global ordering across a topic is usually not guaranteed — only within a partition/key. If
PostUpdated can arrive before PostCreated, subscribers must handle it (partition by
postId to keep one post's events in order). And like queues, pub/sub is at-least-once:
subscribers must be idempotent, because every subscriber can receive the same event twice.
Practice
Recap
- Pub/sub inverts the dependency: producers publish one event to a topic and don't know their subscribers; consumers depend on the event, not the producer.
- One publish fans out to every subscriber, and each consumes on its own independent backlog — so you add reactions by adding subscribers, never by touching the producer.
- The costs are no single "done" moment, weak cross-topic ordering, and at-least-once delivery — keep must-complete steps synchronous and make subscribers idempotent.
Message Queues
Point-to-point delivery for distributing work to one worker.
Monolith vs Microservices
Why Adda's services need to react to each other's events at all.
Idempotency
Surviving the duplicate deliveries pub/sub will hand you.
In an interview
How to discuss this
Frame pub/sub as "this happened" events versus a queue's "do this task." The line that scores points: the producer publishes once and doesn't know its subscribers, so new reactions are added without redeploying the producer. Then volunteer the hard parts — no single completion moment, ordering only within a partition key, and at-least-once duplicates — and say keep the critical write synchronous while everything else reacts asynchronously.
How is this guide?
Last updated on
Message Queues
A video attached to an Adda post takes 90 seconds to process — and it's holding the upload request hostage. When Adda goes viral, that one slow task takes down the whole API. A queue absorbs the shock.
Rate Limiting
A bot with a broken retry loop hammers Adda's search endpoint 50,000 times a second and drowns everyone else. Nabila draws the line: rate limiting caps how much any one client can ask for.