コンテンツにスキップ

システム設計:スケーラブルな通知サービスの設計(Email/Push/SMS)

問題

Every app sends notifications (Emails, Push, SMS). Design a scalable notification system.

解答・設計

要件定義

機能要件:
  - 数百万件の通知を送信できる
  - Email / Push / SMS の複数チャネルに対応
  - 失敗時にリトライできる

非機能要件:
  - 高スループット(ピーク時に数万件/秒)
  - 高可用性(通知の欠損は許されない)
  - チャネルごとに独立してスケールできる

アーキテクチャ設計

フロー:
Event → Notification Service → Queue → Workers → Channels

[イベントソース]
  - ユーザーアクション(注文完了・フォローなど)
  - スケジュールバッチ(朝のメール配信など)
  - 内部サービスからの呼び出し


[Notification Service]
  - ユーザー設定取得(どのチャネルで通知するか)
  - テンプレート解決(通知文面の生成)
  - チャネルごとにキューへ振り分け


[Message Queue] (Kafka / SQS / RabbitMQ)
  - email-queue
  - push-queue
  - sms-queue
  → チャネルごとに分離してスケール可能


[Workers] (チャネルごとに独立)
  - Email Worker → SendGrid / AWS SES
  - Push Worker  → FCM (Android) / APNs (iOS)
  - SMS Worker   → Twilio / AWS SNS


[外部プロバイダー]

重要な設計ポイント

1. キューで非同期化する
   → 通知の送信は即時でなくてよい
   → 外部プロバイダーへの依存をデカップリング
   → プロバイダーがダウンしても通知は失われない

2. リトライ戦略
   → Exponential Backoff: 1s → 2s → 4s → 8s...
   → 最大リトライ回数を設定(例: 5回)
   → Dead Letter Queue(DLQ)で失敗分を保管・分析

3. 冪等性(Idempotency)
   → 同じ通知を2回送らない
   → notification_id を使って重複チェック(Redis で管理)

4. レートリミット
   → 外部プロバイダーのレート制限に従う
   → ユーザーへの過剰通知を防ぐ(1日N件まで)

5. ユーザー設定の優先
   → 通知オフ設定・Do Not Disturb 時間帯を尊重
   → Preference Service を分離して管理

データモデル

-- 通知ログ
CREATE TABLE notifications (
  id            UUID PRIMARY KEY,
  user_id       UUID NOT NULL,
  channel       ENUM('email', 'push', 'sms'),
  template_id   VARCHAR(100),
  status        ENUM('pending', 'sent', 'failed'),
  retry_count   INT DEFAULT 0,
  created_at    TIMESTAMP,
  sent_at       TIMESTAMP
);

-- ユーザー通知設定
CREATE TABLE notification_preferences (
  user_id       UUID PRIMARY KEY,
  email_enabled BOOLEAN DEFAULT TRUE,
  push_enabled  BOOLEAN DEFAULT TRUE,
  sms_enabled   BOOLEAN DEFAULT FALSE,
  quiet_hours_start TIME,
  quiet_hours_end   TIME
);

スケール見積もり

前提: DAU 1000万、1ユーザーあたり平均5通知/日
  → 5000万通知/日 ≈ 578通知/秒(平均)
  → ピーク時は10倍 ≈ 5780通知/秒

キューの分散:
  - Email: 300/秒 → Worker 3台
  - Push:  250/秒 → Worker 2台
  - SMS:   28/秒  → Worker 1台

面接でのポイント

  • 「キューで非同期化」「チャネルごとにワーカーを分離」の2点は必須
  • リトライ・冪等性・DLQ まで言及すると信頼性の理解を示せる
  • ユーザー設定(Do Not Disturb)への言及で UX 観点も評価される
  • 数値見積もりを出せると定量的な設計力として加点