Спроектируйте систему уведомлений: push, email и SMS от разных сервисов компании, с настройками пользователя, ретраями и защитой от дублей.
Короткий ответ
- Единая точка входа: сервисы шлют событие, а не сами рассылают
- Очередь на канал: push, email, SMS обрабатываются независимо
- Проверка настроек и rate limit до отправки
- Внешние провайдеры ненадёжны: ретраи с экспоненциальной задержкой
- Дедупликация по ключу события — пользователь не получит дубль
- Шаблоны и локализация отдельно от логики доставки
- Статусы доставки и DLQ для разборов
Система уведомлений — это приёмник событий, очереди по каналам, воркеры с ретраями к внешним провайдерам, дедупликация по ключу и централизованные настройки пользователя.
Как сказать вслух
пример ответаЯ сделаю уведомления отдельным сервисом с одной точкой входа, чтобы продуктовые команды просто публиковали события. Дальше очереди по каналам и воркеры, которые ходят к провайдерам с ретраями. Обязательно дедупликация, иначе при ретраях пользователь получит одно письмо дважды.
Подробный ответ
Основной ответ
Продуктовые сервисы публикуют событие (тип, получатель, payload, ключ идемпотентности) в сервис уведомлений — синхронно по API или через шину. Сервис валидирует, применяет настройки пользователя (отписки, тихие часы, частотные лимиты, выбор каналов) и раскладывает задачи в очереди по каналам. Воркеры каждого канала рендерят шаблон и вызывают провайдера (APNs/FCM, SES/SendGrid, SMS-шлюз). Ошибки провайдера ретраятся с экспоненциальным backoff и джиттером; после N попыток задача уходит в dead letter queue. Дедупликация по ключу события в Redis/БД гарантирует не более одной отправки. Статусы (отправлено, доставлено, открыто) пишутся для аналитики и отладки.
Ключевые моменты
- Развязка через очередь. Всплеск событий (маркетинговая рассылка) не валит провайдеров и не блокирует продуктовые сервисы — очередь сглаживает нагрузку.
- Идемпотентность. Ключ события проверяется перед отправкой; at-least-once доставка из очереди плюс дедупликация дают эффективный exactly-once для пользователя.
- Настройки и лимиты. Централизованная проверка отписок и частотных ограничений — иначе каждая команда реализует её по-своему и ошибается.
- Ретраи и DLQ. Backoff с джиттером не добивает провайдера после сбоя; DLQ сохраняет неотправленное для ручного разбора вместо тихой потери.
Практический контекст
Интервьюер проверяет умение работать с ненадёжными внешними зависимостями: ретраи, идемпотентность, деградация при отказе провайдера (переключение на запасного). Уточните: допустима ли задержка в минуты для email при мгновенном push, нужны ли транзакционные и маркетинговые уведомления с разными приоритетами, какой объём в пике. Сильный кандидат сам предложит приоритетные очереди и запасного провайдера.
Частые ошибки
- Каждый продуктовый сервис сам ходит к провайдерам — настройки и отписки дублируются и расходятся
- Ретраят без дедупликации, и пользователи получают одно уведомление по несколько раз
- Забывают про настройки пользователя и частотные лимиты — система технически работает, но спамит