Design a Notification System
Prompt
"Design a notification service. Internal product teams call it to send push, email, and SMS to users. It has to handle a burst where one event notifies millions of people, and it must not send the same notification twice."
Clarifying questions
- Who are the callers? Internal services, via an API. They pass a user id or a list of user ids, a template, and parameters. No end-user-facing composition UI.
- Channels? Mobile push (via the platform push services), email, and SMS. In-app inbox is a follow-up.
- Ordering guarantees? Per user, notifications from one source should arrive in order when practical; no global ordering.
- Delivery guarantee? At-least-once to the external provider, with deduplication so users do not see duplicates. Some loss under extreme failure is tolerable for low-priority notifications, not for transactional ones (a security alert must arrive).
- User preferences? Yes: opt-outs per channel and category, quiet hours, and rate caps per user per day.
- Scale? Hundreds of millions of users; steady state of tens of thousands of notifications per second with bursts of tens of millions in a few minutes.
- Latency? Transactional notifications within seconds; marketing or digest notifications can take minutes.
- Do we track delivery and opens? Delivery status yes; opens for email and push where the provider reports them.
Requirements
Functional
- Accept a notification request for one or many users; render a template per user and channel; deliver via the right provider.
- Respect user preferences, quiet hours, and per-user caps.
- Deduplicate: a retried request or a retried internal step must not produce a second delivery.
- Track status per notification and expose it to callers.
- Prioritise transactional over bulk traffic.
Non-functional
- High availability for accepting requests; the API should ack quickly and process asynchronously.
- Burst absorption: a spike of 10M+ notifications should be enqueued in seconds and drained at provider-limited rates without dropping steady-state transactional traffic.
- Observability: per-channel delivery rates, provider errors, and end-to-end latency.
Back-of-envelope
- Steady state: assume 30,000 notifications/s average across channels, 60% push, 35% email, 5% SMS. That is 18,000 push/s, 10,500 email/s, 1,500 SMS/s.
- Burst: a broadcast to 20M users in 5 minutes → 67,000 notifications/s on top of steady state, but provider rate limits (assume the push provider caps us at tens of thousands of sends per second per app, and email providers at a similar order) mean the drain rate, not the enqueue rate, is the bottleneck. The queue must hold the whole burst: 20M × 1 KB ≈ 20 GB. Trivial for a durable log.
- Storage for status: each notification produces a status record of ~300 B kept for 30 days. 30,000/s × 86,400 × 30 × 300 B ≈ 23 TB. Sharded by notification id with time-based expiry.
- Device registry: 500M users × 2 devices × 200 B (token, platform, app version, last seen) ≈ 200 GB. Read on every push; cache heavily.
- Preference lookups: one per (user, category) per notification → 30,000 lookups/s steady, 100,000/s in bursts. Cache with a short TTL; the source is a small table.
- Template rendering: 30,000 renders/s of a small template is a few dozen cores; not a constraint.
- Dedup store: keys for the last 24 hours → 30,000 × 86,400 ≈ 2.6B entries × 40 B ≈ 100 GB. A sharded in-memory store with TTL, or a bloom filter in front of a persistent set.
Last reviewed 8 September 2026
High-level design · Data model & APIs · Deep dives · Failure modes & follow-ups · Level rubric · Company variations
The rest of this question — the worked approach, the design walkthrough, complexity, follow-ups and how each company frames it — is part of the guides.
Get the full guide
Pick the company you're interviewing with. Each guide has every question tiered for that loop — one-time purchase, lifetime access.
Also in: Apple, Google, Meta, Microsoft, Netflix
Interviewing at more than one? All 6 guides for $499 · save $395
Not ready to buy? Get the free starter pack — 13 questions with full solutions.