The Message That Arrived Twice
The two pieces before this one were about how much you send and who controls it. The last question is mechanical: what happens on the way out. A notification is an external side effect — an email handed to a provider, a push handed to a platform, a webhook posted to somebody’s endpoint — and every one of those hops can fail in the ambiguous way the retries thread described, where the call didn’t come back but the work may well have happened. Retry it and the customer gets two. Don’t and they may get none.
Duplicates are worth taking seriously because of how visible they are. Most bugs are invisible to customers; a doubled email is a bug that arrives in their inbox with your name on it, and three of them look like a system out of control. The fix is the same as everywhere else in this pattern: give each notification a stable identity derived from the event rather than from the attempt, record what’s been sent, and check before sending. That turns “did this already go out” from a guess into a lookup, which is the only version that survives a retry.
The other half is that “sent” isn’t “delivered,” and the gap contains real information. Providers report bounces, blocks, and hard failures, and a system that ignores those reports accumulates addresses it will never reach while believing it’s still in touch. Someone whose email has been bouncing for six months is, from the product’s perspective, receiving everything — which means every workflow that depends on notification actually working is quietly broken for them. Reading delivery feedback and surfacing a persistently unreachable contact is unglamorous and prevents a specific kind of slow customer loss.
Then there’s ordering, which mostly matters because notifications describe state that keeps changing. “Your report is ready” arriving after “your report failed” is confusing; a status update landing out of order can tell someone the opposite of the truth. The durable fix isn’t to guarantee ordering across an external channel you don’t control — it’s to make each message make sense on its own, stating the state as of a moment rather than narrating a transition the reader may receive backwards.
Which closes the thread. Notifications look like the simplest thing in a product — some text, an address, send — and they sit on top of everything this blog keeps returning to: aggregate volume nobody owns, preferences that only work if every path respects them, at-least-once delivery, ordering you don’t control, and failure modes that are invisible internally and highly visible externally. Worth treating as a system rather than a feature, because that’s what it is once more than one thing in the product can send.