Chaturmind
LearnDSASystem DesignBlogPremium
Sign inGet started
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML

Company

  • Blog
  • Premium
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← System Design Interview Playbook

Interview Framework

  • The 6-Step Design Framework

10 Case Studies

  • Design a URL Shortener
  • Design Twitter / X
  • Design WhatsApp
  • Design Netflix
  • Design a Rate Limiter
  • Design a Search Autocomplete
  • Design a Distributed Cache
  • Design a Notification Service
  • Design Uber / Ride Sharing
Chaturmind
← System Design Interview Playbook

Interview Framework

  • The 6-Step Design Framework

10 Case Studies

  • Design a URL Shortener
  • Design Twitter / X
  • Design WhatsApp
  • Design Netflix
  • Design a Rate Limiter
  • Design a Search Autocomplete
  • Design a Distributed Cache
  • Design a Notification Service
  • Design Uber / Ride Sharing
HomeLearnSystem DesignSystem Design Interview PlaybookDesign Cases
✓ FreeIntermediate· 12 min read

Design: Notification Service

Design a multi-channel notification system supporting push, email, SMS with delivery guarantees.

Published April 27, 2025


Design: Notification Service

Requirements

  • Send notifications via: Push (iOS/Android), Email, SMS
  • 10M+ notifications/day
  • Delivery guarantees: at-least-once
  • User preferences: opt-out per channel
  • Deduplication: don't send the same notification twice

Architecture

Producer Services (Order, Payment, Social) 
  → Notification API
  → Message Queue (Kafka)
  → [Channel Workers]
     ├── Push Worker → APNs (iOS) / FCM (Android)
     ├── Email Worker → SendGrid / SES
     └── SMS Worker → Twilio / SNS

Data Model

-- Notification requests
CREATE TABLE notification_requests (
    id           UUID PRIMARY KEY,
    user_id      UUID NOT NULL,
    type         VARCHAR(50),  -- 'ORDER_SHIPPED', 'MESSAGE_RECEIVED'
    channel      VARCHAR(20),  -- 'PUSH', 'EMAIL', 'SMS'
    payload      JSONB,
    status       VARCHAR(20),  -- PENDING, SENT, FAILED
    created_at   TIMESTAMP,
    sent_at      TIMESTAMP
);

-- User notification preferences
CREATE TABLE notification_preferences (
    user_id      UUID,
    channel      VARCHAR(20),
    type         VARCHAR(50),
    enabled      BOOLEAN DEFAULT TRUE,
    PRIMARY KEY (user_id, channel, type)
);

Delivery Flow

// Notification Worker (per channel)
public void processNotification(NotificationEvent event) {
    // 1. Check user preferences
    if (!preferences.isEnabled(event.userId, event.channel, event.type)) {
        return; // user opted out
    }

    // 2. Deduplication check
    String dedupeKey = event.userId + ":" + event.idempotencyKey;
    if (redis.setnx(dedupeKey, "1") == 0) {
        return; // already sent
    }
    redis.expire(dedupeKey, 86400); // 24h window

    // 3. Send via provider
    boolean sent = false;
    for (int retry = 0; retry < 3 && !sent; retry++) {
        try {
            sendViaProvider(event);
            sent = true;
        } catch (Exception e) {
            Thread.sleep(exponentialBackoff(retry));
        }
    }

    // 4. Update status
    notificationRepo.updateStatus(event.id, sent ? "SENT" : "FAILED");

    // 5. Requeue on failure (dead letter queue)
    if (!sent) deadLetterQueue.publish(event);
}

Handling Provider Failures

Primary provider fails:
  1. Retry with exponential backoff (1s, 2s, 4s)
  2. Fallback to secondary provider
  3. Dead letter queue for manual retry

Queue backpressure:
  - Multiple workers per channel
  - Auto-scale workers based on queue depth

Priority Queues

High Priority: security alerts, OTP codes → immediate
Medium Priority: order updates → within 1 minute
Low Priority: marketing, newsletters → within 1 hour

Separate Kafka topics per priority

Interview Tips

  1. Idempotency key is essential — without it, retries cause duplicate notifications.
  2. The queue-based architecture naturally provides buffering and backpressure — explain this.
  3. User preference checks must be fast — cache in Redis, not DB.

Previous

Design a Distributed Cache

Next

Design Uber / Ride Sharing

AI Tutor

Lesson: Design: Notification Service

Quick actions

AI responses can be inaccurate. Verify critical information.