#кейс. Event Sourcing в масштабе.
Event Sourcing в масштабе: где проходит граница чистой архитектур
Представим реальный масштаб.
1200 сервисов. 30 команд. Нужно собирать события пользователей : аутентификация, платеж, перевод и т.д.
Эти события нужны двум разным системам: — система мониторинга ошибок и проактивных действий — система безопасности (борьба с мошенничеством)
Контексты разные. Потребности разные. Пересечение данных — около 50%.
Обе системы принимают события через Kafka.
И дальше возникает ключевой архитектурный вопрос:
> Каждый сервис должен публиковать события сразу в две Kafka ?
> или сбор и разделение нужно вынести в отдельный слой?
Наивный вариант
Самый очевидный путь — в каждом сервисе реализовать две публикации: — Kafka A — Kafka B
Локально это выглядит просто. Глобально — почти всегда становится проблемой.
Альтернатива: единый поток и Projector
Мы смотрим на сервис как на владельца доменных событий.
Сервис: — пишет данные в БД — публикует один гарантированный поток событий (через outbox)
Дальше появляется отдельный слой — Projector: — читает события — трансформирует — фильтрует — маршрутизирует — публикует в нужные Kafka-кластеры
Это решение выглядит «архитектурно красиво». Но важно честно разобрать плюсы и риски.
Плюсы: почему это чисто
1. Чёткая граница ответственности Сервис отвечает только за: — доменную модель — корректность событий
Вопросы «куда и в каком виде можно отдавать данные» уезжают из сервиса.
Это сильная clean boundary.
2. Безопасность и комплаенс Логика: — маскирования — фильтрации — разрешённых полей
находится в одном месте, а не размазана по 1200 кодовых баз.
3. Стабильность контрактов Можно разделить: — внутренний канонический формат событий — внешние витрины под конкретные системы
Эволюция схем становится управляемой.
Минусы: где архитектура может сломаться
Чистота здесь не бесплатная.
1. Риск «интеграционного монолита» Если Projector начинает: — принимать бизнес-решения — агрегировать смысл — «умно» интерпретировать события
он быстро превращается в монолит интеграций.
2. Зоопарк трансформаций Если разные команды начинают: — добавлять свои правила — усложнять логику — решать локальные задачи
архитектура деградирует.
Вывод по чистоте
Подход остаётся чистым только при жёстком ограничении роли Projector.
Допустимо: — field mapping — фильтрация — версионирование — маскирование — маршрутизация
Недопустимо: — предметная логика — бизнес-правила — принятие решений за домен
Почему «публиковать в две Kafka из каждого сервиса» чаще хуже
На масштабе 1200 сервисов этот вариант почти всегда проигрывает по TCO.
1. Dual-write и консистентность Сервису нужно гарантировать: — DB — Kafka A — Kafka B
Даже с outbox это означает: — два outbox’а или — один outbox и два независимых продьюсера
Риски: — в одну Kafka ушло, в другую нет — сложные ретраи — дедупликация — расследования инцидентов
2. Операционная нагрузка ×1200 Удваивается всё: — конфиги — security / ACL / TLS — клиентские библиотеки — версии — инциденты «падает внешний кластер»
И всё это — на 30 команд.
3. Безопасность и доверие
Если одна из Kafka — другой домен доверия, ключевое правило минимизация данных.
Держать логику «что можно наружу»
в 1200 сервисах = почти гарантированный дрейф.
4. Эволюция контрактов Схемы, версии, совместимость
намного проще: — централизовать — контролировать — версионировать
в одном слое, чем синхронизировать изменения в сотнях сервисов.
Итоговый вывод
В масштабе: — 1000+ сервисов — десятков команд — разных контекстов потребления
модель: один доменный поток → централизованный Projector → несколько Kafka
чаще всего выигрывает по: — управляемости — безопасности — стоимости владения
Но это работает только при дисциплине.
Projector — это инфраструктурный слой, а не место для бизнес-логики.
Как только эта граница нарушается чистая архитектура заканчивается.
Мой канал - https://t.me/manager_dot_exe