Skip to main content
HS
HiSETSuccess
LeetCode Prep

System Design

Comprehensive interview guide: scalability, databases, distributed systems, cloud architecture, and full case-study walkthroughs — plus adaptive quizzes.

Case study

Design a Notification System

Deliver push, email, and SMS notifications at scale with user preferences and provider failover.

fan-outtemplatesmulti-channel

Requirements

  • Functional: send notifications via push (FCM/APNs), email, SMS; user channel preferences
  • Support transactional (password reset) and marketing (promo) with different priorities
  • Templates with variable substitution; schedule future delivery
  • Non-functional: transactional p99 delivery < 30 sec; at-least-once with idempotency
  • Scale: 100M users; 1B notifications/day

Back-of-envelope Estimation

MetricCalculationResult
Total/day1B notificationsMixed channels
Avg QPS1B / 86,400~12K/sec
Peak QPS5× avg (campaign blast)~60K/sec
Push (60%)600M/dayFCM handles burst; batch where possible
Email (30%)300M/day~3.5K/sec avg via SendGrid/SES
Storage (logs, 90 days)1B × 200 B × 90~18 TB

API Design

EndpointDescription
POST /v1/notifications{ userId, templateId, channels[], data, idempotencyKey }
GET /v1/notifications/{id}/statusqueued | sent | delivered | failed
PUT /v1/users/{id}/preferencesChannel opt-in/out, quiet hours
POST /v1/templatesAdmin: create template per channel

Data Model

EntityFields
notification_eventsevent_id, user_id, template_id, payload, idempotency_key, status, created_at
delivery_attemptsattempt_id, event_id, channel, provider, status, error, ts
user_preferencesuser_id, push_enabled, email, sms, quiet_hours_start/end
device_tokensuser_id, platform, token, last_seen

High-level Design

Notification pipeline
Producer ──► API ──► validate prefs ──► Router
                                      │
                    ┌─────────────────┼─────────────────┐
                    ▼                 ▼                 ▼
              Push queue        Email queue       SMS queue
                    │                 │                 │
              FCM/APNs          SendGrid/SES        Twilio
                    └─────────────────┴─────────────────┘
                                      │
                              Delivery status DB

Deep Dive: Priority & Rate Limiting

  • Separate Kafka topics: transactional (priority 0), standard, marketing (priority 2)
  • Per-user rate limit: max 10 marketing/day; transactional bypasses limit
  • Quiet hours: queue until window opens unless urgent flag
  • Idempotency: dedupe table keyed by idempotency_key for 24h

Deep Dive: Provider Retries & DLQ

Exponential backoff: 1s, 5s, 30s, 5min (max 5 attempts). Invalid device token → mark dead, stop retry. Provider 5xx → retry; 4xx permanent → DLQ for manual review.

Batch push

FCM supports 500 tokens per multicast. Group users by template and send in batches to reduce API calls during campaigns.

Failure Modes & Monitoring

SLOTarget
Transactional delivery p99< 30 sec
End-to-end success rate> 99% (excluding invalid tokens)
DLQ depth< 10K events
  • Alert: provider error rate > 5%, queue lag > 5 min, dedupe collision spike
  • Dashboard: delivery funnel by channel, template performance, opt-out rate