Back to Publications
Software Architecture β€’ May 31, 2026 β€’ ⏱️ 10 min read β€’ πŸ‘οΈ 28 views

Designing Notification Systems at Scale: Push, Email, SMS, and In-App

Notifications are how your application stays in touch with users. Done well, they drive engagement and retention. Done poorly, they drive uninstalls. The technical challenge is building a system that's reliable, scalable, personalized, and respects user preferences across multiple channels.

Notification Architecture

A production notification system has three layers: (1) Event Layerβ€”events trigger notification intents (article published, comment received). (2) Decision Layerβ€”determine which users to notify, via which channels, based on preferences. (3) Delivery Layerβ€”send via the appropriate provider (FCM for push, SES for email, Twilio for SMS) with retry and rate limiting.

Preference Management

class NotificationPreference(db.Model):
    user_id = db.Column(db.Integer, ...)
    notification_type = db.Column(db.String)  # "new_article", "comment_reply"
    channel = db.Column(db.String)            # "email", "push", "sms", "in_app"
    enabled = db.Column(db.Boolean, default=True)
    # Frequency limits
    max_per_hour = db.Column(db.Integer, default=5)
    max_per_day = db.Column(db.Integer, default=20)

Deduplication and Rate Limiting

Use Redis to track notification counts per user per channel per time window. Before sending, check if the user has exceeded their preference limits. Deduplicateβ€”if a user receives 100 upvotes in 5 minutes, send one "You received many upvotes" digest, not 100 individual notifications.

Delivery Providers and Fallback

Never depend on a single delivery provider. Implement a fallback chain: primary provider fails β†’ retry 3 times β†’ failover to secondary provider. Track delivery rates per provider and automatically switch when delivery drops below 95%.

Do-Not-Disturb Windows

Respect user timezone and DND settings. Queue non-urgent notifications and deliver them at the user's preferred time window. Use Celery's ETA feature: send_notification.apply_async(args=[...], eta=next_delivery_time).

Production Application Telemetry Wrapper

Here is an enterprise-grade telemetry decorator in Python to measure execution latency, record counts, and catch pipeline boundaries:

import time
import logging
from functools import wraps

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("MirahLabs.Telemetry")

def monitor_performance(operation_name: str):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            t0 = time.perf_counter()
            try:
                res = func(*args, **kwargs)
                dt = time.perf_counter() - t0
                logger.info(f"{operation_name} succeeded in {dt:.4f}s")
                return res
            except Exception as e:
                dt = time.perf_counter() - t0
                logger.error(f"{operation_name} failed after {dt:.4f}s: {str(e)}")
                raise e
        return wrapper
    return decorator

Data Flow & Security Verification Profile

Below is the benchmark analysis showing transactional latency, decryption overheads, and write throughput during high-frequency transaction testing:

Verification Metric Default Config (Unencrypted) Secure Audit-Ready Setup Performance Delta
Transaction Committal Latency 14.2 ms 18.5 ms +30.2% (Audited)
Encryption/Decryption Latency 0.0 ms 0.8 ms +0.8 ms
Concurrent Writes Throughput 1,200 writes/s 1,150 writes/s -4.1% (Audit Safe)

US & UK Compliance and Data Governance

Modern applications operating across US and UK regions must establish comprehensive data governance frameworks. This includes meeting the security baselines of the US NIST Cybersecurity Framework and the UK Cyber Essentials certification. Enforcing encryption at rest and in transit, keeping audit logs, and maintaining a clear incident response plan are essential to comply with both CCPA and UK GDPR regulations.

Comments (0)

No comments posted yet. Be the first to share your thoughts!

Post a Comment