Design a service that sends notifications — mobile push, SMS and email — for events like "order shipped" or "exam results published" for a few million users. How do you make it reliable, avoid duplicate messages, and respect user preferences?
Show hints
Decouple accepting a notification from actually delivering it.
Show the explanation
Model answer.
Requirements
- Channels: push (via APNs for iOS, FCM for Android), SMS (via an SMS gateway) and email (via an email provider or SMTP).
- Triggered by other services; some notifications are scheduled.
- Respect user opt-outs and quiet hours; at-least-once delivery without spamming duplicates; delivery status tracking.
High-level components
- Notification API: other services call it with
{userId, templateId, data, idempotencyKey}. It validates the request and returns quickly. - Preference and contact lookup: fetch the user's enabled channels, device tokens, phone and email (cached for speed). Drop channels the user has opted out of.
- Message queue (Kafka, RabbitMQ or SQS), with a separate queue or topic per channel, so a slow SMS provider does not delay push notifications.
- Channel workers: consume from the queue, render the template, call the external provider, and record the result.
- Notification log database: status per message (queued, sent, delivered, failed) for tracking and support.
- Scheduler: stores future notifications and enqueues them when due.
Reliability
- The queue buffers bursts (e.g. results day) so the system degrades into delay rather than failure.
- Workers retry failed sends with exponential backoff; after several failures the message goes to a dead-letter queue for inspection.
- Workers acknowledge a queue message only after the provider accepts it, giving at-least-once delivery.
Avoiding duplicates
At-least-once delivery means a message can be processed twice (for example, a worker crashes after sending but before acknowledging). Store the idempotency key and check it before sending; skip messages already marked sent.
Other considerations
- Per-user rate limits so a bug cannot send 50 messages to one person.
- Prioritise transactional messages (OTPs) over marketing.
- Remove invalid device tokens reported by APNs/FCM.
- Templates with localisation (English, Hindi, Telugu, etc.).
Common follow-up: "Can you guarantee exactly-once delivery to the user's phone?" Not end-to-end — external providers and networks can duplicate or drop. You aim for at-least-once processing plus deduplication, which gives effectively-once behaviour in most cases.
Original UniCircle question. Last reviewed 28 Oct 2026.
