Step 1: Requirements and estimates
Start by asking what kinds of notifications exist, because they behave very differently:
- Transactional: caused by something the user did or that concerns them directly: “order shipped”, “new message”, “password changed”. Expected, time-sensitive, usually can’t be turned off entirely (security alerts).
- Marketing: campaigns sent to many users at once: “sale this weekend”. Optional, must respect opt-outs and laws, and can wait a little.
Functional requirements:
- Channels: push (iOS, Android), email, SMS, in-app inbox.
- Other services call one API: “notify user 42 with template
order_shippedand these values”. - Users choose per category and channel (no marketing push, yes order emails).
- Quiet hours in the user’s time zone, except for urgent messages.
- Scheduling (“send at 9 a.m. local time”) and campaigns to millions of users.
Non-functional: no duplicates, no lost transactional notifications, urgent ones within seconds even during a campaign, and an audit trail of what was sent.
Probe for: priority classes (security and OTP vs social vs marketing), legal constraints (consent and unsubscribe for email, SMS regulations, GDPR deletion), per-user frequency caps, localization, multi-device fan-out, delivery and engagement tracking, and who owns templates. The architecture follows from three properties: requests are bursty (campaigns), providers are external and rate-limited, and delivery is at-least-once internally, so idempotency and isolation by priority and channel matter more than raw throughput.
Users: 50 million, ~1.5 devices each
Transactional notifications: ~200 million / day → ~2,000 / s average, ~10,000 / s peak
Marketing campaign: 20 million users in one campaign
sent within 15 minutes: 20e6 / 900 s ≈ 22,000 / s on top of normal traffic
Push to providers: each notification × devices (1.5) ≈ 50,000 device pushes / s peak
Email: a few million per day, mostly transactional receipts
SMS: only OTPs and critical alerts: expensive (cents per message)
Storage (log of what was sent): ~250 million records / day × ~300 B ≈ 75 GB / day, kept ~90 days- Bursty: the busiest moments are campaigns, which can be ten times the normal rate.
- Urgent must not wait behind bulk: a password-reset code stuck behind 20 million sale announcements is a broken login.
- SMS is expensive, so it’s reserved for things like one-time codes.
- Transactional vs marketing; channels push/email/SMS/in-app; preferences per category × channel; quiet hours in local time; scheduling and campaigns.
- No duplicates, no lost transactional messages, urgent latency in seconds during campaigns, audit trail.
- Campaign bursts (~20M in 15 min ≈ 22k/s) dominate; providers are rate-limited; SMS costly; legal consent and unsubscribe.
Check this part
Why must transactional and marketing notifications be handled separately?
What drives peak load in a notification system?