System Design: Notification System
Modern apps send billions of notifications daily — push, email, SMS, in-app. A scalable system must be reliable, multi-channel, and handle user preferences.
Architecture
Event Sources (user action, payment, system alert)
|
v Notification Service
- Load user preferences
- Filter channels (quiet hours, disabled channels)
- Fanout to Kafka per channel
|
+── Push Worker (FCM for Android, APNs for iOS)
+── Email Worker (AWS SES / SendGrid)
+── SMS Worker (Twilio)
+── In-App Worker (store in DB, fetch on next open)
|
v Delivery Log (success/fail/bounce tracking)
Push Notification Worker
from firebase_admin import messaging
def send_push(user_id: int, title: str, body: str):
tokens = device_repo.get_tokens(user_id)
message = messaging.MulticastMessage(
tokens = [t.token for t in tokens],
notification = messaging.Notification(title=title, body=body),
)
response = messaging.send_multicast(message)
for i, r in enumerate(response.responses):
if not r.success and 'invalid' in str(r.exception).lower():
device_repo.deactivate(tokens[i].id)
Q: How to ensure exactly-once delivery?
Use idempotency keys: store notification_id in sent_notifications table. Before processing, check if already sent. At-least-once delivery (Kafka) plus idempotency check equals exactly-once semantics in practice.
Comments (0)
No comments yet. Be the first!
Leave a Comment