Design a Multi-Channel Notification System
Company: Replit
Role: Software Engineer
Category: System Design
Difficulty: medium
Interview Round: Onsite
## Design a Multi-Channel Notification System
Design a system that accepts notification requests and delivers them through configured channels such as in-app, email, SMS, or mobile push. Include user preferences, templates, scheduling, retries, deduplication, provider failures, and delivery observability.
### Constraints & Assumptions
- A logical notification may produce several channel deliveries, each with its own status.
- At-least-once queues and third-party providers can create duplicate attempts.
- Some notifications are transactional and time-sensitive; others may be batched or suppressed.
- User consent, quiet hours, channel availability, and locale are evaluated from versioned preferences.
- Required throughput, latency, retention, regions, and delivery guarantees must be clarified.
### Clarifying Questions to Ask
- Which channels and provider capabilities are required?
- Which notification classes may ignore quiet hours or user marketing preferences?
- Does success mean accepted by a provider, delivered to a device, or read by a user?
- Are ordering, scheduled delivery, cancellation, digests, and localization required?
- What rate limits apply per tenant, user, channel, and provider?
### Part 1 — Define the Request and Preference Contract
Specify APIs and records for submitting, scheduling, canceling, and reading notification status. Define templates, recipients, channels, preferences, and idempotency.
#### What This Part Should Cover
- Stable logical-notification and channel-delivery IDs.
- Caller-scoped idempotency keys and normalized request hashes.
- Template version, locale, variables, and validation.
- Preference and consent evaluation with an auditable policy result.
```hint Separate intent from delivery attempts
One notification request can create several channel deliveries, and each delivery may need more than one provider attempt.
```
### Part 2 — Route and Deliver Reliably
Design the path from durable acceptance to channel workers and providers. Address scheduling, priority, retries, timeouts, provider callbacks, and deduplication.
#### What This Part Should Cover
- Durable request and outbox state before acknowledging acceptance.
- Separate channel queues and provider adapters with bounded concurrency.
- Stable provider idempotency keys where supported.
- Retry classification, exponential backoff, expiry, and dead-letter handling.
```hint Make every retry identify the same delivery
A timeout leaves the provider outcome unknown, so retry or reconcile the existing delivery instead of creating a new logical notification.
```
### Part 3 — Apply Policy and Control Load
Explain quiet hours, frequency limits, digests, fallback channels, cancellation races, tenant isolation, and overload behavior.
#### What This Part Should Cover
- The exact time at which preferences and consent are evaluated or rechecked.
- Per-user and per-tenant rate limits plus provider backpressure.
- A declared fallback policy that does not multiply unwanted messages.
- Bounded queues, expiration, and priority fairness.
```hint Recheck rules that can change
A scheduled notification accepted yesterday may no longer be permitted when its delivery time arrives.
```
### Part 4 — Observe and Reconcile Outcomes
Define status semantics, provider-event processing, audit trails, metrics, and repair of deliveries stuck between states.
#### What This Part Should Cover
- Accepted, suppressed, queued, attempted, provider-accepted, delivered, failed, and expired states as supported.
- Signed callback validation and duplicate or out-of-order event handling.
- Reconciliation of unknown provider outcomes.
- Metrics for lag, delivery, retries, suppression, duplicates, and provider health.
```hint Report the strongest known fact
Provider acceptance is not the same as device delivery, and an absent callback is not proof that delivery failed.
```
### What a Strong Answer Covers
- Durable, idempotent intent and distinct channel-delivery and attempt state.
- Consent-aware routing, bounded retries, provider isolation, and honest status semantics.
- Tenant and user rate control with graceful overload behavior.
- Reconciliation, auditability, and stage-specific observability.
### Follow-up Questions
1. How would you cancel a scheduled message racing with a worker claim?
2. What should happen when an email provider times out after accepting the request?
3. How would a preference change affect already queued marketing notifications?
4. How would you migrate traffic between two push providers without duplicating deliveries?
Quick Answer: Design a notification platform that routes one logical request across in-app, email, SMS, or push channels under user preferences. The system must handle templates, scheduling, consent, idempotency, provider retries, rate control, cancellation races, reconciliation, and status semantics that distinguish acceptance from delivery.