Skip to content
UniCircle
MediumDesignAsynchronous processing

Design a notification system (push, SMS, email)

Question SD-106

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

  1. Notification API: other services call it with {userId, templateId, data, idempotencyKey}. It validates the request and returns quickly.
  2. 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.
  3. Message queue (Kafka, RabbitMQ or SQS), with a separate queue or topic per channel, so a slow SMS provider does not delay push notifications.
  4. Channel workers: consume from the queue, render the template, call the external provider, and record the result.
  5. Notification log database: status per message (queued, sent, delivered, failed) for tracking and support.
  6. 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.