# Case Study: Notifications and Order Events — Redis Pub/Sub & Streams

Source: https://www.skillbyai.com/en/redis-streams/p-case

> 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.

```text
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.

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

- [x] 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.
