Skip to main content
Pub/Sub Patternlesson 3 of 3 · 2 min read

Ordering and Delivery Caveats

Two weaker promises

Pub-sub makes two promises weaker than newcomers expect, and both bite you in production instead of in testing.

Take ordering first. A system that partitions or fans out has no global order at all, so messages you published a millisecond apart can reach a subscriber the wrong way round.

What brokers actually give you is order within a lane. A Kafka partition keeps order for messages sharing a key, and the FIFO queues do the same per group.

Choose the key that matters, then, because that is the whole design move. Key your events by order and each order's created, paid, shipped sequence stays intact. That events for different orders interleave is fine, since no promise spans them.

Choose badly, or add partitions to a topic without thinking, and a subscriber sees shipped before paid.

Carry a version number or a timestamp in the payload anyway, and ignore anything stale. Rebalances and retries can still shuffle things at the edges even when your keys are right.

Delivery

Take delivery second. Almost everything durable is at least once, so every subscriber sees occasional duplicates, most often around restarts when acknowledgements are in flight.

Reach for the same remedies as with queues: handlers that can run twice safely, and deduplication on the event identifier. With several subscribers the duplicated work multiplies, because each one deduplicates on its own.

Know your broker's floor before you rely on it. A fire-and-forget broadcast delivers only to whoever is connected, so a subscriber restarting during your deploy silently misses everything published in the gap.

Summarise it the way you would in an interview. Pub-sub gives you order within a lane and at-least-once delivery at best, so write every subscriber as though messages will arrive late, twice, or slightly shuffled. Eventually they will.

the shape of it
PublisherPartition Aorder 4412Partition Border 9981Subscriber1. keyed by order2. different key3. in order4. interleaved
step 1 of 4
Order holds inside a partition, so the key you choose decides what stays ordered.

Worked example

Jae builds shipment tracking on a Kafka topic where warehouse systems publish scan events. To spread load, the producer team partitions by warehouse station ID, so one package's scans, arriving through different stations, land on different partitions. Two percent of packages start showing out-for-delivery before arrived-at-facility, and support tickets follow. Repartitioning by package ID would fix future events but the topic already has consumers depending on its layout, so Jae fixes the subscriber instead: each scan carries the warehouse's monotonic sequence number, and the tracker stores the highest sequence applied per package, discarding any event at or below it. Late and duplicate scans now update nothing. When a consumer group rebalance during a deploy redelivers 4,000 already-processed scans, the dedup check absorbs all of them, and the tracking page shows every package's timeline in the right order.

Pub/Sub Pattern: wrapping up

In the real world

  • 01Twitter's home timeline has been publicly described as hybrid fan-out: regular users' tweets are written into follower timelines at post time, while celebrity tweets are merged in at read time to avoid tens of millions of writes per post.
  • 02The documented AWS pattern for durable fan-out is SNS topics delivering into one SQS queue per subscriber, giving each consumer independent buffering, retries, and dead letter queues.
  • 03Kafka consumer groups let each subscribing team read the full event stream at its own offset, which is how one event topic can feed search indexing, analytics, and fraud detection without coordination.
  • 04Redis pub-sub delivers only to currently connected subscribers with no persistence, and Redis added Streams in version 5.0 largely because teams needed a replayable alternative.
  • 05Google Cloud Pub/Sub provides per-subscription acknowledgment tracking and at-least-once delivery globally, with ordering keys as an opt-in feature because ordered delivery costs throughput.

Questions people ask

What is the difference between a message queue and pub-sub?

A queue distributes each message to exactly one of its consumers, which suits jobs that should be done once. Pub-sub delivers a copy of each message to every subscriber, which suits events that multiple independent systems care about. Most brokers support both shapes: SQS is a queue, SNS is pub-sub, and Kafka does both through consumer groups.

Does pub-sub guarantee my subscribers receive messages in order?

Not globally. Brokers preserve order only within a lane, a Kafka partition key or an SQS FIFO message group, and messages in different lanes interleave arbitrarily. Choose a key that matches your invariants, like order ID or user ID, and build subscribers to tolerate occasional reordering anyway, using sequence numbers or versions to discard stale events.

When is fire-and-forget pub-sub like Redis acceptable?

When missing a message is harmless because the next one supersedes it or the state can be re-fetched. Cache invalidation broadcasts, presence updates, and live dashboard ticks all qualify. Anything with business meaning, orders, payments, audit events, needs a durable broker where a subscriber that was down gets its backlog on return.

Quick review

Unlike point-to-point queues, every subscriber gets a copy of every message on subscribed topic
Kafka:
topic partitioned for parallelism. Each consumer group independently consumes all messages
Google Cloud Pub/Sub / AWS SNS:
fully managed. SNS fan-out to SQS queues for durable per-subscriber buffering
Redis Pub/Sub:
fire-and-forget. Subscriber must be connected at publish time, no persistence
Use cases:
cache invalidation across nodes, notifications, event sourcing, audit log, microservice event bus
Fan-out on write:
when a user posts, fan-out service writes to each follower's feed queue (Twitter model)
Fan-out on read:
compute feed at request time by fetching followed-users' posts (simpler writes, slower reads)
the trade-off

Fan-out on write: expensive for accounts with millions of followers. Fan-out on read: slow at scale. Use hybrid.

in the room

Event-driven architectures. Notifications. Cache invalidation. Any 1-to-N communication pattern.