Запросить демо
Триггерные сценарии

Event sourcing для триггерных рассылок: архитектура CDP

Event sourcing в CDP: когда оправдан, как реализовать, какие риски. Архитектура триггерных рассылок с journaling и CQRS.

Категория
Триггерные сценарии
Время чтения
6 минут
Опубликовано
Автор
stackfort

Ключевые выводы

  • Event sourcing для триггерных рассылок — архитектурный подход, при котором каждое изменение состояния системы фиксируется как неизменяемое событие в журнале
  • Этот паттерн особенно ценен в CDP, потому что даёт полный аудит-след, возможность переигрывать события и точную замену любых пропущенных коммуникаций
  • Альтернатива — CRUD-подход с обновлением состояния «на месте», который проще, но не позволяет восстановить хронологию решений
  • Главные риски event sourcing: рост объёма данных, сложность отладки, eventual consistency между event store и проекциями
  • Решение применимо для CDP с 5+ млн профилей и плотным engagement-слоем — для меньших проектов overhead не оправдан

Event sourcing для триггерных рассылок — архитектурный паттерн, который превращает CDP из «базы текущего состояния» в «журнал всех решений и действий». При этом подходе каждое событие — клик, покупка, вход в приложение, отправка коммуникации — записывается как неизменяемая запись с timestamp и контекстом, и состояние системы вычисляется как проекция этого журнала.

В этой статье разберём, когда event sourcing для триггерных рассылок оправдан, а когда — преждевременная оптимизация, и как его правильно реализовать в on-prem CDP.

Что такое event sourcing в контексте CDP

Стандартный подход в CDP: есть таблица customer_profiles, в ней колонка last_purchase_date обновляется каждый раз, когда происходит покупка. Если завтра нужно узнать, что у клиента было «вчера в 18:00» — невозможно: данные перезаписаны.

Event sourcing работает иначе: в системе есть журнал событий (event store), и каждая покупка — это новая запись в нём. Состояние клиента (например, last_purchase_date) — это проекция, рассчитанная из событий до конкретной точки времени.

Преимущество в одном предложении: ничего не теряется, всё можно переиграть, точное состояние любой точки времени восстановимо.

Зачем event sourcing для триггерных рассылок

Точное воспроизведение пропущенных кампаний

В реальной эксплуатации регулярно случается: новый сценарий запустили на 100 тысяч клиентов, но первая 10% волна получила некорректное сообщение. С event sourcing достаточно отыграть события и переотправить только тем, у кого статус доставки был неуспешным. Без event sourcing — приходится перепосылать всем 100 тысячам или ничего не делать.

Точный аудит-след для compliance

На запросе Роскомнадзора «покажите, какие коммуникации получал клиент X в марте 2025» с event sourcing ответ — выгрузка из event store за нужный период. Без event sourcing — реконструкция по логам разных систем с пробелами.

Гибкость в развитии сценариев

Появилась новая бизнес-метрика — «среднее время между двумя последними покупками». В CRUD-подходе её нужно начинать считать с момента введения. С event sourcing — отыгрываем все события и получаем метрику для всей истории.

Корректная обработка опоздавших событий

Событие «клик по email» пришло с опозданием в 2 дня (сетевые проблемы у мобильного приложения). В CRUD это создаёт некорректное состояние. В event sourcing — событие просто добавляется в нужное место хронологии.

Архитектура event sourcing для CDP

Event store — основной журнал

Append-only хранилище всех событий. Технически реализуется через:

  • Kafka с retention=infinite — стандартный подход, но требует управления партициями
  • Apache Pulsar — современная альтернатива с tiered storage
  • PostgreSQL с partitioning по дате — для проектов с объёмом до 100 млн событий
  • Cassandra или ClickHouse — для очень больших объёмов

Проекции — текущее состояние

Из event store рассчитываются проекции — таблицы текущего состояния, которые читают приложения. Например:

  • Profile projection: текущие данные профиля клиента
  • Segment projection: к каким сегментам относится клиент сейчас
  • Communication projection: какие коммуникации получил клиент
  • Loyalty projection: текущий статус, баллы, кэшбэк

Каждая проекция строится отдельно, может пересчитываться независимо, может быть удалена и пересоздана из event store.

Command-query separation (CQRS)

Event sourcing обычно идёт в паре с CQRS — разделением операций записи и чтения. Команды (например, «отправить email») создают новые события в event store. Запросы (например, «какой статус сегмента у клиента X») читают из проекций.

Реализация триггерных рассылок поверх event sourcing

  1. Событие «купил товар» приходит в event store
  2. Сценарный движок подписан на этот тип события и вычисляет, нужна ли рассылка
  3. Команда «отправить email» создаёт событие email_sent_command
  4. Worker отправки подписан на email_sent_command, выполняет отправку через SMTP
  5. Событие «email доставлен»/«email открыт» приходит обратно в event store
  6. Проекция communications обновляется и показывает текущий статус коммуникации

Каждый шаг — это отдельное событие. Если на шаге 4 произошла ошибка отправки, можно retry без потери контекста: событие email_sent_command не теряется, оно остаётся в event store с pending-статусом.

Когда event sourcing оправдан

  • База клиентов 5+ млн профилей с активным engagement
  • Compliance-требования к аудит-следу всех решений и действий
  • Сценарии с возможностью «переиграть» пропущенные кампании или ошибки
  • Команда с опытом распределённых систем (3-5 senior-инженеров)
  • Желание иметь полную хронологию состояний для product analytics

Когда event sourcing — преждевременная оптимизация

  • База клиентов меньше 1 млн профилей — overhead не оправдан
  • Команда без опыта event-driven архитектур
  • Простые маркетинговые задачи без compliance-аудита
  • Жёсткие требования к latency запросов (event sourcing добавляет 50-200мс)
  • Отсутствие потребности в repeatability и reproducibility

Главные подводные камни

Рост объёма данных

Событий в event sourcing намного больше, чем строк в CRUD. Проект с 5 млн профилей и 10 событий/день/клиент даёт 50 млн новых событий в день, 1.5 млрд в месяц. Хранить такие объёмы без партиционирования и архивирования — экономически невыгодно.

Eventual consistency

Между событием в event store и обновлением проекции — секунды или минуты. UI и автоматизация должны учитывать, что состояние «отстаёт» от реальности. В простых CRUD-системах этого нет.

Сложность отладки

В event sourcing для понимания «почему клиент попал в такой сегмент» нужно посмотреть всю цепочку событий — это сложнее, чем посмотреть текущую запись в БД. Требуются специальные инструменты — event replay, debug-проекции.

Schema evolution

Поскольку события неизменяемы, изменение схемы события — серьёзная задача. Старые события остаются в старом формате, новые события в новом, и проекции должны работать с обоими. Часто требуется upcasting — программная конвертация старых событий в новый формат при чтении.

Стек инструментов

СлойРоссийские вариантыOpen source
Event storeYandex MDB Kafka, VK Cloud KafkaApache Kafka, Pulsar, EventStoreDB
Stream processingKafka Streams, Flink, Spark
ПроекцииPostgreSQL, ClickHouseCassandra, Elasticsearch
CQRS-фреймворкКастомная разработкаAxon Framework, EventStoreDB
МониторингPrometheus, Grafana

FAQ о event sourcing для триггерных рассылок

Можно ли совместить event sourcing с outbox pattern?

Да, и это часто оптимальная комбинация. Event sourcing — для журнала бизнес-событий, outbox pattern — для гарантированной доставки команд между сервисами. Подробнее об outbox pattern — в нашем материале по архитектуре триггерных рассылок без Kafka.

Сколько стоит event sourcing-инфраструктура?

Минимум 3-5 млн ₽ дополнительно к стандартной CDP-смете на инфраструктуру (Kafka-кластер, расширенное хранилище) и 2-3 млн ₽ на разработку базовой архитектуры. Для среднего проекта это +20-30% к бюджету.

Что такое snapshot-pattern в event sourcing?

Это оптимизация: периодически сохраняется текущее состояние агрегата (например, профиля клиента), и при пересчёте проекции используется ближайший snapshot плюс события после него. Это сокращает время восстановления состояния с минут до секунд.

Можно ли использовать event sourcing только для части системы?

Да, и это часто разумный подход. Например, event sourcing для коммуникаций и сегментации, а CRUD — для базовых данных профиля. Гибридная архитектура снижает риски и позволяет получить преимущества event sourcing там, где они наиболее ценны.

Как тестировать event sourcing-систему?

Через сценарии с заданным набором событий и проверкой результирующего состояния проекций. Важно покрывать тестами не только happy path, но и опоздавшие события, дубликаты, события в неожиданном порядке. Это требует специализированных тестовых фреймворков и часто — отдельной test-роли в команде.

Что в итоге

Event sourcing для триггерных рассылок — мощный архитектурный паттерн, который даёт CDP возможности аудита, repeatability и эволюции, недостижимые в CRUD-подходе. Цена — рост сложности, объёмов данных и команды.

Применять стоит для проектов от 5 млн профилей с серьёзными compliance-требованиями. Для меньших — гибридный подход или классический CRUD с подробным логированием.

Готовы помочь оценить применимость event sourcing к вашему контексту и спроектировать архитектуру — обсудим в формате архитектурной консультации.