TSTier SlateAll templates

Messaging & realtime

Notification router - one event, the right channel, once

How one event is turned into email, push or SMS by preferences and quiet hours, without sending it twice.

  • System design
  • core
  • 8 step walkthrough
  • 6 tables

Share

  • Facebook
  • X

What this board gets wrong on purpose

The tension

The claim makes a replay harmless but not a crash: a sender that dies after the provider accepted the message and before it marks the claim sent leaves a row stuck in "claimed", and the recovery sweep must either resend it (a duplicate) or drop it (a loss) without knowing which happened - the board resends, so "once" means once except in a window of about 200 ms per send. The push-to-email fallback is a second notification by design, triggered by "not opened in ten minutes", and push cannot tell "not opened" from "not delivered", so users who simply saw the banner and ignored it get the email too. Quiet hours are computed from a timezone saved at signup, so a traveller is woken at 3am. And everything deferred overnight is released at 08:00 local, so each timezone produces a morning spike of about 20,000 sends a second unless the release is smeared - which the deferred queue does with jitter, and the SMS provider's per-second rate limit still caps.

Practise this as an interview

Take Notification router - one event, the right channel, once as a timed system design interview on a blank board - on your own, with the requirements to check yourself against, or with a candidate you invite.

Practise this as an interview

Start here

Why this design

Every product with users ends up with a notification system, usually by accident: each team calls the email provider directly, then the push provider, then somebody adds SMS for one feature. Within a year users are getting the same alert on three channels at 2am and support cannot say why. A notification router is the one place that decides channel, timing and deduplication for every notification in the company. Interviewers like it because it mixes product rules (preferences, quiet hours, digests) with a real distributed systems guarantee (once per channel over an at-least-once bus).

What you will learn

  • Separating "what happened" (an event) from "who should hear about it, how, and when" (routing), and why producers must never pick channels.
  • Preferences and consent as data: per notification type, per channel, with legal opt-in for SMS and marketing.
  • Quiet hours in the user's timezone, deferral until morning, digests, and the morning thundering herd they create.
  • Exactly once per channel via a unique claim, and the crash window that remains.
  • Fallback across channels, and why it is a deliberate duplicate.

How to read this board

  1. Press Play and follow the walkthrough: SOURCES on the left, then the ROUTE column hanging down from the router.
  2. Then ONCE in the middle - the claim between deciding and sending.
  3. Then CHANNELS and providers on the right, and the user.
  4. 1 · Requirements to 6 · Deployment in the written band, then the DATA MODEL.
  5. Then argue with the tension: once except for a crash window, a fallback that duplicates on purpose, and a timezone that travels.

1 · Requirements

Ask these before drawing anything

  • Which notifications are transactional (password reset, payment failed, security alert) and which are engagement or marketing? The two have different legal rules, different quiet-hours rules, and must never share a send queue.
  • Who decides the channel - the producing team or the user? The answer must be the user, through preferences, with the notification type providing defaults.
  • What does "once" mean - once per event, or once per channel per event? A shipped order on push AND email is usually intended. The same push twice never is.
  • Is SMS in scope, and who pays for it? At a cent or more per message, SMS is reserved for opt-in, critical notifications.
  • How fresh must a preference change be? If a user turns off a type and gets one more five seconds later, is that a bug report?

Functional

  • Consume domain events (order.shipped, comment.created, login.new_device) from the event bus.
  • For each recipient, select channels from type defaults, user preferences and consent.
  • Apply quiet hours in the user's timezone; defer non-urgent notifications to 08:00 local.
  • Collapse bursts of low-priority notifications into a digest within a 15 minute window.
  • Send each notification at most once per (event, user, channel), even when the event is delivered more than once.
  • Fall back from push to email when a push is not opened within ten minutes, for types that opt in.
  • Record delivery receipts, bounces, opens and unsubscribes.

Non-functional

  • Transactional notifications: event to provider handoff in under 5 seconds at p99.
  • Engagement notifications: under 15 minutes, or the next 08:00 local.
  • Preference changes take effect within 30 seconds.
  • Duplicates per channel below 1 in 100,000 sends.
  • Unsubscribe honoured immediately and auditable for regulators (CAN-SPAM, GDPR, TCPA for SMS).

The rest of this board

Board preview

Available on Tier Slate

This page publishes the question. The answer — 5 more written pages, an 8-step narrated walkthrough and a 6-table schema — is the board itself, and it opens in Tierslate.

  • 5written pages
  • 8walkthrough steps
  • 6tables44 columns

5 pages behind this one

  • Capacity estimation
  • Storage estimation
  • Availability
  • How it works
  • Deployment plan
Open this board in TierslateBrowse every board

More boards

Delivery, presence, ordering, and who is typing.

  • Chat and messaging - one socket, many deliveries
  • Transactional email - the receiver decides
  • Presence - the most expensive cheap feature
  • Push notifications - the token outlives the install
  • Team channels - the unread count is the hard part
  • Encrypted delivery - one tick, two ticks, blue
  • Webhook delivery - retrying into somebody else's outage
All 100 templatesOpen Tierslate
Tierslate

tierslate.com

HomeTemplatesPrivacyTerms