Design: Notification Service
IntermediateA notification service delivers messages to users via multiple channels (push, email, SMS, in-app). It must handle high throughput, user preferences, rate limiting, and reliable delivery with retries.
Overview
A notification service is a shared platform that other services use to notify users. An order service sends "order shipped" to the notification service, which figures out the channels (push notification, email, SMS) based on user preferences and delivers via the appropriate provider (FCM/APNs for push, SendGrid for email, Twilio for SMS). Key design considerations: (1) Decoupling — producers send notification requests to a message queue; consumers process them asynchronously. (2) Multi-channel delivery — support push, email, SMS, in-app with per-user channel preferences. (3) Rate limiting — prevent notification fatigue (max 5 push notifications/hour). (4) Templates — reusable notification templates with variable substitution. (5) Reliability — retry failed deliveries, track delivery status, dead-letter queue for permanent failures. (6) Priority — urgent notifications (OTP, security alerts) jump the queue ahead of marketing messages.
Architecture
Producers send notification requests to a queue. The notification service processes them: resolves user preferences, renders templates, and dispatches to channel-specific workers.
// Notification service architecture
//
// Order Service ─┐
// Auth Service ──┤ Notification Request
// Payment Svc ──┤ (user_id, type, data)
// │
// ▼
// ┌──────────────┐
// │ Kafka Topic │ (notification-requests)
// └──────┬───────┘
// │
// ▼
// ┌──────────────┐
// │ Notification │ 1. Look up user preferences
// │ Service │ 2. Render template
// │ │ 3. Route to channel queues
// └──┬────┬───┬──┘
// │ │ │
// ▼ ▼ ▼
// Push Email SMS ← channel-specific queues
// Queue Queue Queue
// │ │ │
// ▼ ▼ ▼
// FCM/ Send- Twilio ← external providers
// APNs GridUser Preferences & Templates
Users configure which channels they want notifications on. Templates are pre-defined with variables that are filled at send time.
// User notification preferences
{
"userId": "u-42",
"channels": {
"push": { "enabled": true, "quiet_hours": "22:00-07:00" },
"email": { "enabled": true },
"sms": { "enabled": false }
},
"categories": {
"order_updates": ["push", "email"],
"marketing": ["email"],
"security": ["push", "sms", "email"] // all channels for security
}
}
// Notification template
{
"templateId": "order_shipped",
"channel": "push",
"title": "Order Shipped! 🚀",
"body": "Your order {{orderId}} has been shipped. Track: {{trackingUrl}}",
"action": { "type": "deep_link", "url": "/orders/{{orderId}}" }
}
// Rate limiting per user:
// Push: max 5 per hour (except security category)
// Email: max 3 per day for marketing
// SMS: max 2 per day (expensive channel)Reliability & Priority
Retry failed deliveries with exponential backoff. Use priority queues to ensure OTP and security notifications are delivered instantly. Track delivery status for each notification.
// Priority levels
// P0 (Critical): OTP, security alerts → processed immediately
// P1 (High): order updates, payment confirmations → < 1 min
// P2 (Normal): social updates, recommendations → < 5 min
// P3 (Low): marketing, newsletters → batched, sent in windows
// Separate queues by priority
// Kafka topics: notifications-p0, notifications-p1, notifications-p2, notifications-p3
// P0 consumers: more instances, higher throughput
// P3 consumers: fewer instances, batch processing
// Delivery status tracking
// notification_id | user_id | channel | status | timestamp
// notif-1 | u-42 | push | SENT | 10:00:01
// notif-1 | u-42 | push | DELIVERED | 10:00:02
// notif-1 | u-42 | email | SENT | 10:00:01
// notif-1 | u-42 | email | BOUNCED | 10:00:05 → retry
// Retry: exponential backoff (1s, 2s, 4s) up to 3 attempts
// After max retries → move to DLQ for investigation
// Idempotency: notification_id + channel = unique (no duplicate sends)Key Points to Remember
- 1Decouple notification requests from delivery using message queues — producers are not blocked.
- 2Multi-channel delivery (push, email, SMS, in-app) based on user preferences per notification category.
- 3Priority queues ensure critical notifications (OTP, security) are never delayed by marketing.
- 4Rate limiting prevents notification fatigue — configurable per channel and per user.
- 5Retry with backoff + DLQ for reliable delivery; idempotency keys prevent duplicate sends.
Interview Questions
Sign in to ask AriaHow would you design a notification service supporting push, email, and SMS?
How do you handle user notification preferences across channels?
How do you ensure critical notifications like OTPs are delivered instantly?
How do you prevent duplicate notifications from being sent?
Design a notification platform that sends 1 billion notifications per day.
Ask Aria about Design: Notification Service
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.