System Design · Design Question
Design a Notification System
Multi-channel notifications: push, SMS, email — templates, preferences, fan-out, retries, and provider abstraction.
1. Requirements
- Send notifications on events (order shipped, new follower, OTP).
- Channels: mobile push (FCM/APNs), email, SMS; in-app inbox optional.
- User preferences and quiet hours; unsubscribe / opt-out.
- At-least-once delivery to providers; idempotent per notification id.
- High throughput bursts (campaigns) without killing transactional OTPs.
2. API
3. Data model
4. High-level design
5. Deep dives
Priority lanes
OTP and security alerts get a dedicated high-priority queue and provider account so a marketing blast cannot starve them.
Idempotency
Fan-out
One event → N devices. Expand device tokens in the push worker; batch provider APIs where supported. Soft-fail invalid tokens and remove them.
Rate limits
Respect provider quotas; token-bucket per channel. Backpressure via consumer lag metrics.
6. Scaling
- Partition Kafka by
userIdfor per-user ordering if needed. - Autoscale workers on lag; separate pools per channel.
- Template + prefs cached in Redis.
- Multi-region: send from region near user or near provider endpoints.
7. Observability
- Acceptance rate, provider latency, bounce/complaint rates.
- DLQ depth alerts; replay tooling.
8. Edge cases
- User disables SMS → skip channel, still try push if allowed.
- Partial success: email sent, push failed → retry push only.
- PII in templates → redact logs; encrypt at rest.
9. Template rendering
Keep templates versioned. Render with strict escaping to avoid injection
into HTML email. Support locale fallback: en-IN → en.
Preview API for product teams reduces production mistakes.
10. Compliance
- SMS/email marketing needs opt-in evidence; transactional may differ by region.
- Honor unsubscribe links quickly; store preference changes durably.
- Log delivery without logging OTP codes in plaintext.
Quick revision
- Accept API → durable queue → channel workers → providers.
- Separate transactional vs bulk lanes.
- Prefs, quiet hours, templates before send.
- Idempotency keys prevent duplicate OTPs/blasts.
- Track per-channel attempts; DLQ poison messages.
- Respect provider rate limits; clean invalid push tokens.
- Priority: never let marketing block OTP.