Design notification service
Email, SMS, push. Easy to sketch, and the retry question is where it gets real.
standard · 45 minutes · 8 classes
Requirements
- Send a notification over one of several channels — email, SMS, push.
- Per-user preferences decide which channels are eligible.
- Templates rendered with per-notification data.
- Retry transient failures; give up on permanent ones.
- Rate-limit per user so nobody gets twenty messages in a minute.
Say these are out of scope
- Building the actual delivery infrastructure — assume vendor SDKs exist.
- Analytics on opens and clicks.
- Internationalisation of template copy.
A shape that works
One reasonable decomposition, not the only one. What matters in the round is that you can defend the boundaries you drew.
What they'll push on
Which failures do you retry?
Transient ones only. A 500 or a timeout is worth retrying with exponential backoff and jitter; a 400, an unsubscribed address or an invalid number will fail identically forever and retrying just burns quota. The channel result has to distinguish the two — a boolean success flag isn't enough.
The send succeeds but your process dies before recording it.
You'll retry and the user gets it twice. At-least-once is the honest default, so make delivery idempotent with a key per (user, event, channel) that the sender checks. Claiming exactly-once across a network boundary is the wrong answer and interviewers listen for it.
Why is each vendor behind an adapter?
Because your code should depend on Channel, not on a vendor's SDK shape. Swapping providers becomes one new adapter rather than edits at every call site, and it gives tests a seam — otherwise every test needs the network.