SkillByAIOpen interactive version →

Lesson 24 / 25

Case Study: Notifications and Order Events

Combine Pub/Sub and Streams in one realistic design.

The right primitive for each job

A food-delivery app needs three things. Order events (OrderPlaced, OrderPicked, OrderDelivered) must be processed reliably by billing, rider assignment and analytics. These go through an outbox relay into 8 partitioned streams keyed by order ID, each with consumer groups per service, idempotent handlers keyed by event ID, XAUTOCLAIM every 30 seconds for stuck entries, a dead-letter stream after five deliveries, and retention of about 48 hours by MINID trimming. Live order tracking in the customer app is pushed through WebSocket servers that use sharded Pub/Sub channels per order ({order:o-1001}:tracking); messages may be lost during reconnects, so the app refetches the current status from the API after reconnecting. Local cache invalidation for restaurant menus uses a Pub/Sub channel, with a 60-second TTL as a safety net. The Redis deployment for streams runs with AOF everysec, noeviction, a replica in another zone, and alerts on group lag, pending growth and memory.

The design summary

Each need uses the primitive whose guarantees fit it.

need                       primitive                         guarantees / safeguards
-------------------------  --------------------------------  ----------------------------------------
order events (must process) 8 partitioned streams + groups    outbox, XACK, idempotency, XAUTOCLAIM,
                                                             dead-letter stream, 48 h MINID retention
live tracking to the app   sharded Pub/Sub per order         loss tolerated; app refetches on reconnect
menu cache invalidation    Pub/Sub channel                   60 s local TTL as safety net
operations                 AOF everysec, noeviction,         alerts: lag, PEL growth, memory, idle
                           replica in another zone           consumers with pending entries

Mixing primitives is normal

Using Pub/Sub for ephemeral updates and Streams for business events in the same system is good design, as long as each team knows which guarantee applies to which channel or stream.

Quick check: In the case study, why is live tracking sent with Pub/Sub rather than Streams?

  • Tracking updates are ephemeral and the app can refetch the current status after reconnecting, so occasional loss is acceptable
  • Pub/Sub stores messages longer
  • Streams cannot be used with WebSockets
  • Pub/Sub guarantees exactly-once delivery
Answer

Tracking updates are ephemeral and the app can refetch the current status after reconnecting, so occasional loss is acceptable — Ephemeral, refreshable data does not need the storage and acknowledgement overhead of streams.