Every notification service starts as one function called send. It ends as the most fragile part of the system.
The pain shows up late. A user gets the same payment alert three times: push, WhatsApp, and email. Or worse, gets nothing at all because their push token expired two months ago and no one owned that failure. Support hears about it before monitoring does.
The reason is that teams model notifications as delivery, when the hard part is state. Which channels does this user actually have? Which ones are still valid? Was this event already delivered somewhere else? Is this notification worth waking someone up for, or is it a digest item?
We have built fan-out services pushing to WhatsApp, Telegram, mobile and web push, and the pattern that survived production was treating the event and the delivery as separate objects. One event, many delivery attempts, each with its own status. Deduplicate on the event, not the message. Keep channel preferences and token validity in one place that both the product team and the compliance team can read. And make silent failure loud: an expired token that fails quietly is indistinguishable from a happy user until it isn't.
The unglamorous version of this is a table of delivery attempts you can query. That table is what turns "the user says they never got it" from an argument into a lookup.
For teams running multi-channel notifications: where did yours first break down — deduplication, preference management, or token and identifier decay?