Платформа данных и захват событий
Версия: 1.0 Дата: 26.04.2026 Статус: Готов к обсуждению
Назначение документа
Документ определяет платформу данных (data platform) Vitiana и слой захвата событий (events tracking) — два центральных компонента оси данных и интеллекта (data and intelligence spine, ось 4). Включает:
- Каноничную модель аналитического события (
AnalyticalEvent). - Главное правило разделения доменных событий (domain events) и аналитических событий (analytical events).
- Поток захвата событий — точки захвата на поверхностях взаимодействия, нормализацию, обогащение.
- Каноничную модель хранилища данных (data warehouse, DWH) — таблицы фактов, таблицы измерений, секционирование (partitioning), медленно меняющиеся измерения (slowly changing dimensions).
- Классы приватности полей (privacy classes per data field).
- Правила межтенантной агрегации (multi-tenant aggregation rules).
- Ограничение цели (purpose limitation), политика хранения (retention policy) — связь с обязательствами по общему регулированию защиты данных.
- Поток обработки данных и потоковую обработку (ETL/streaming pipelines).
- Закрытие технического долга 8 из реализации
home-to-go-api. - Фазы развёртывания.
Документ читается после:
- Ось данных и интеллекта — пять компонентов оси, главные принципы. Этот документ детализирует компоненты 1 (захват событий) и 2 (хранилище данных).
- Соответствие требованиям регуляторов § 11.6 — соответствие, влияющее на платформу данных.
- Связь с реализацией → Долг 8 — текущее смешанное хранилище в
events_themes, которое надо разделить. - Событийная шина и асинхронная дисциплина — как доставляются доменные события.
- Первоначальная таксономия событий — какие доменные события уже зафиксированы.
В корневых документах зафиксировано что платформа данных делает и почему разделяет два класса событий. Этот документ описывает как — каноничные сущности, потоки, правила приватности, фазы.
Платформа данных — критическая инфраструктура для всех остальных слоёв интеллекта (машинного обучения, A/B-экспериментов, аналитики, биллинга по фактическому потреблению). Без зрелой платформы данных нельзя ни ранжировать поиск, ни тарифицировать партнёров, ни предотвращать возвратные платежи, ни строить рекомендации.
Правило 00000 (платформа главенствует над поставщиками) применяется здесь напрямую: каноничная аналитическая модель не подгоняется под форматы аналитики поставщиков. Платформа задаёт каноничную схему аналитики; поставщики предоставляют сырые данные, нормализуемые слоем приёма данных в каноничную форму.
Главное решение
Доменные события и аналитические события — два разных класса с разными гарантиями, разными шинами, разными хранилищами, разной политикой приватности, разной скоростью движения.
Это означает:
| Свойство | Доменные события (domain events) | Аналитические события (analytical events) |
|---|---|---|
| Назначение | Изменение каноничной доменной модели — BookingConfirmed, QuoteCreated, OfferPublished, PaymentCaptured | Поведенческие следы — SearchExecuted, OfferViewed, FacetApplied, ProposalShared |
| Источник | Сервисы платформы (внутренние) | Поверхности взаимодействия (внешние клики и запросы) |
| Гарантии доставки | Хотя бы один раз (at-least-once) с упорядоченностью по сущности | Хотя бы один раз с допустимой потерей малой доли |
| Шина | Событийная шина платформы (event bus, на фазе 2 — Managed Kafka) | Tracking pipeline (отдельная шина, на фазе 2 — отдельные топики или отдельный поток) |
| Хранилище | Журнал событий (event log) + базы операционных контуров | Хранилище данных (DWH) — Snowflake / ClickHouse / BigQuery paradigm |
| Скорость | Реальное время (миллисекунды до секунд) | Real-time + batch (секунды для streaming, часы для daily aggregations) |
| Приватность | Минимальная PII (актёры идентифицированы по tenant_id + actor_id) | Анонимизация на захвате (хешированные идентификаторы, обобщённая геолокация) |
| Срок хранения | Долгий (audit trail, годы) | Класс-зависимый (см. секцию политики хранения) |
| Потребители | Операционные контуры платформы (booking, search, payment) | Аналитика, ML-модели, A/B-эксперименты, отчётность |
Это архитектурный закон, не «оптимизация». Смешение двух классов в одном хранилище разрушает свойства каждого:
- Доменные события в DWH — теряют операционные гарантии.
- Аналитические события в журнале операционных событий — раздувают operational store, ломают политику хранения, ломают приватность.
Это закрепляет долг 8 из реализации (см. далее).
Каноничная модель аналитического события
Сущность AnalyticalEvent
{
event_id: UUID,
event_name: string,
event_class: string,
event_version: string,
occurred_at: timestamp,
ingested_at: timestamp,
tenant_id: UUID,
surface_id: enum,
session_id: UUID,
actor_hash: string,
client_locale: string,
client_currency: string,
client_geo_class: string,
client_device_class: string,
context: object,
attributes: object,
privacy_class: string,
retention_class: string,
schema_id: string
}
Поля и их семантика
event_id— каноничный идентификатор события, генерируется на стороне поверхности взаимодействия для идемпотентности.event_name— каноничное имя события из таксономии. Например,search.query.executed,offer.viewed,proposal.shared.event_class— широкая группа:discovery/proposal/booking_funnel/post_booking/partner_intent/system_health.event_version— версия схемы события. Изменения схемы — через инкремент версии без ломающих изменений старой.occurred_at— момент события на стороне источника (поверхности).ingested_at— момент захвата события платформой. Разница даёт задержку конвейера.tenant_id— какой тенант инициировал событие (источник трафика).surface_id— какая поверхность (partner_api/b2c_storefront/agency_working/tour_builder_closed/internal_admin).session_id— ссылка на сессию (поисковую, пользовательскую, агентскую). Не содержит чувствительных данных.actor_hash— анонимизированный идентификатор актёра. Хеш с солью, ротация соли по политике приватности.client_locale,client_currency,client_geo_class,client_device_class— обобщённый клиентский контекст без точной геолокации (только страна + регион), без точной модели устройства (только классdesktop/mobile_phone/tablet).context— структурированный контекст события (ссылки на сущности, к которым относится событие). Например, дляsearch.query.executed— параметры запроса. Дляoffer.viewed—property_id,offer_id, позиция в выдаче.attributes— атрибуты события для аналитики и ML (без PII, без персональных идентификаторов).privacy_class— класс приватности (см. ниже).retention_class— класс хранения (см. ниже).schema_id— идентификатор схемы события в реестре схем.
Каноничная схема — реестр схем (schema registry)
Каждое имя события (event_name) имеет формальную схему в реестре схем (schema registry). Реестр:
- Содержит все версии каждого события.
- Версии накапливаются — старые не удаляются.
- Изменение схемы — только через инкремент
event_version. Каноничные правила эволюции — те же, что для асинхронных контрактов (см. Реестр ломающих изменений). - Поверхности захвата валидируют события против схемы перед публикацией.
Связь с уже зафиксированной таксономией
В Первоначальная таксономия событий уже зафиксированы доменные события. Аналитические события — отдельная таксономия, дополняющая, не пересекающаяся.
Например:
booking.confirmed(доменное) — изменение каноничной сущностиBooking. Публикуется операционным сервисом booking при успешной фиксации платежа и подтверждении поставщика.booking_funnel.purchase.completed(аналитическое) — поведенческое событие, отражающее завершение пути «поиск → коммерческая фиксация → бронирование» на стороне поверхности взаимодействия. Несёт атрибуты для маркетинговой аналитики, не несёт операционных обязательств.
Оба возникают одновременно, но не одно и то же. Доменное публикуется внутренним сервисом и течёт по event bus в операционные контуры. Аналитическое публикуется поверхностью и течёт по tracking pipeline в DWH.
Поток захвата событий
Поверхность взаимодействия (frontend / SDK / партнёрский клиент)
↓
Локальная буферизация на стороне поверхности
↓
Подпись события, добавление client_geo_class и client_device_class
↓
Отправка батчей на ingestion endpoint платформы
↓
Валидация подписи, валидация схемы по реестру
↓
Применение rate limiting (защита от спама и atak'и на конвейер)
↓
Анонимизация actor_hash (если ещё не анонимизирован)
↓
Применение privacy_class и retention_class по правилам
↓
Публикация в tracking pipeline (отдельная шина)
↓
├── Real-time потребители (deduplication → enrichment → ML feature store)
├── Streaming-обработка (агрегации в реальном времени)
└── Batch-загрузка в DWH (микро-партиции по событию + времени)
Точки захвата
- Партнёрский клиент — программный интерфейс или SDK партнёра отправляет события через специализированный канал отчётности (опциональный, для тарифов с partner-facing analytics).
- Потребительская витрина — встроенный JavaScript-клиент с буферизацией.
- Поверхность для агентств — встроенный клиент с акцентом на рабочий поток агента.
- Tour Builder Closed Surface — отдельный канал для композиционных событий конструктора туров.
- Внутренние сервисы платформы — публикуют аналитические события для системных метрик (
system_healthкласс) через тот же tracking pipeline.
Endpoint захвата (ingestion endpoint)
- Адрес — отдельный поддомен, например
events.<домен>для разделения сетевой нагрузки от программного интерфейса. - Протокол — HTTPS, типично POST с пакетным телом (batch payload).
- Аутентификация — отдельный ключ доступа поверхности, не основной программный ключ. Это снижает блаsт-радиус компрометации.
- Rate limiting — отдельная политика, защищающая от подрывного трафика без блокировки основного программного интерфейса.
Идемпотентность захвата
event_id — главная единица идемпотентности. Tracking pipeline на ingestion обнаруживает дубликаты по (tenant_id, event_id) и отбрасывает их. Это критически важно для:
- Локальной буферизации на стороне поверхности (повторная отправка после потери соединения).
- Партнёрской переотправки (партнёр повторил запрос из-за тайм-аута).
- Replay-сценариев при отладке tracking-пайплайна.
Каноничная модель хранилища данных (DWH)
Принцип отдельного класса хранилища
Хранилище данных — отдельный класс хранилища от operational layer и transactional layer, как зафиксировано в Хранение и Ось данных и интеллекта. Свойства:
- Оптимизировано для аналитических запросов (агрегации, оконные функции, сложные соединения по большим объёмам).
- Колоночное хранение (columnar storage) — типично 10–100× быстрее операционных запросов на агрегации.
- Партиционирование по времени и тенанту.
- Низкая стоимость хранения за единицу — много данных хранится дёшево.
- Eventual consistency приемлема — задержка минут/часов между событием и доступностью в DWH допустима.
Звёздная схема (star schema)
Каноничная модель DWH — звёздная схема с таблицами фактов в центре и таблицами измерений по краям.
Таблицы фактов (fact tables)
fact_search_events— поведенческие события поиска.fact_proposal_events— события презентации предложений (просмотр, шаринг, отбрасывание).fact_booking_funnel— события пути от поиска до бронирования.fact_post_booking— события после бронирования (изменения, отмены, возвраты).fact_partner_usage— потребление платформы партнёром (вызовы, метрики тарификации).fact_payment_events— события платёжного контура.fact_supplier_health— здоровье поставщиков (задержки, доля отказов, свежесть данных).fact_system_health— внутренняя операционная метрика платформы.
Каждая таблица фактов:
- Партиционирована по
event_date(день события) иtenant_id. - Содержит ссылки на ключи измерений (foreign keys).
- Содержит числовые меры (measures) — продолжительность, количество, сумма.
- Не содержит обновляемых полей — только append-only вставки.
Таблицы измерений (dimension tables)
dim_tenant— информация о тенантах с историей изменений (тип медленно меняющегося измерения 2, slowly changing dimension type 2).dim_property— каноничная информация об объектах размещения с историей.dim_supplier— поставщики с историей профилей.dim_partner— партнёры с историей тарифов и классов.dim_geo— иерархия регионов.dim_calendar— календарь дат с признаками (день недели, праздник, сезон).dim_currency— валюты с курсами на конкретные даты.dim_event_schema— версии схем событий с историей изменений.
Медленно меняющиеся измерения (slowly changing dimensions)
Для измерений, чьи атрибуты меняются со временем (например, тариф партнёра), применяется тип 2 медленно меняющихся измерений:
- При изменении атрибута создаётся новая строка с новым
surrogate_key. - Старая строка остаётся, но получает
valid_toдату. - Связи фактов с измерениями делаются по
surrogate_key, что даёт корректный исторический контекст для каждого факта.
Например, если партнёр перешёл со Starter на Professional 1 марта, факты до 1 марта связаны с измерением «Starter», после — с «Professional». Это критично для финансовой отчётности.
Партиционирование (partitioning)
- По времени — таблицы фактов партиционированы по дню (или часу для очень больших объёмов).
- По тенанту — для крупных тенантов выделена отдельная сабпартиция.
- Жизненный цикл — старые партиции (старше политики хранения) автоматически перемещаются в холодное хранилище (cold storage) или удаляются.
Запросы кросс-тенантной агрегации
См. секцию «Правила межтенантной агрегации» ниже.
Классы приватности полей (privacy classes per data field)
Каждое поле в аналитическом событии и в DWH помечается классом приватности:
| Класс | Описание | Пример |
|---|---|---|
pii_strict | Прямой персональный идентификатор. Запрещён в аналитике. | Имя, фамилия, email, телефон, паспорт, IP-адрес как есть |
pii_indirect | Косвенный идентификатор, который в комбинации может идентифицировать. Допустимо только как хеш. | Хеш email, хеш номера телефона |
quasi_identifier | Атрибут, который в сочетании с другими может позволить ре-идентификацию. Требует k-анонимизации (k-anonymity) при экспорте. | Точный возраст, точный почтовый индекс, редкая профессия |
behavioral | Поведенческий след — что пользователь делал. Не идентифицирует напрямую, но может быть привязан к актёру в системе. | Просмотренные предложения, применённые фасеты, время сессии |
aggregate_only | Агрегированные данные, не привязанные к индивидуальному актёру. | Среднее время сессии по тенанту, гистограмма цен |
public | Публичные данные, не относящиеся к персоналиям. | Каноничные имена отелей, регионы, валюты |
Правила обработки по классу
| Класс | Хранится в DWH | Видно ML | Видно партнёрской аналитике | Срок хранения |
|---|---|---|---|---|
pii_strict | ❌ Никогда | ❌ Никогда | ❌ Никогда | Только в operational layer с retention правилами |
pii_indirect | ✅ Только как хеш | ✅ Только как хеш | ❌ | По правилам ниже |
quasi_identifier | ✅ С k-анонимизацией | ✅ С агрегацией | ✅ Только в агрегатах | По правилам ниже |
behavioral | ✅ С actor_hash | ✅ Через feature store | ✅ Только в агрегатах | По правилам ниже |
aggregate_only | ✅ | ✅ | ✅ | Долгосрочно |
public | ✅ | ✅ | ✅ | Бессрочно |
Запрет на повышение класса
Поле, отнесённое к классу pii_strict, не может быть переведено в более низкий класс без явного процесса повторной классификации с обоснованием в реестре схем. Понижение класса требует одобрения от владельца платформы.
Каноничная анонимизация при захвате
Аналитическое событие проходит обязательную анонимизацию на ingestion endpoint:
- IP-адрес → отбрасывается (или заменяется на
client_geo_class). - Прямые идентификаторы (email, телефон) → отбрасываются.
- Косвенные (если переданы) → хеш с солью.
- User agent → парсится в
client_device_class, оригинал отбрасывается.
После анонимизации событие попадает в pipeline. Восстановить исходные данные невозможно — это design choice, не временное упрощение.
Правила межтенантной агрегации (multi-tenant aggregation rules)
Главный принцип
Тенант не видит данные другого тенанта. Это закреплено в Тенантная идентичность и изоляция. DWH следует тому же правилу.
Однако платформа может строить кросс-тенантные агрегаты для:
- Внутренней аналитики платформы (производительность, инциденты, экономика).
- Маркетинговых отчётов агрегированного характера (например, «средняя длительность бронирования по платформе»).
- ML-моделей, обучаемых на данных всех тенантов (без раскрытия индивидуальных данных).
Правила доступа к кросс-тенантным запросам
| Сценарий | Кому разрешено | Условия |
|---|---|---|
| Свои данные тенанта | Тенант, авторизованный сотрудник тенанта | Без условий |
| Кросс-тенантные агрегаты для платформы | Команда платформы (data engineering, finance, leadership) | Через специальные роли с журналом аудита |
| Кросс-тенантные агрегаты для тенанта | Тенант (только агрегаты, не индивидуальные данные) | Минимум N тенантов в агрегате (k_min_tenants), типично 5–10 |
| Кросс-тенантные индивидуальные данные | Никому | Запрещено архитектурно |
| ML-модели, обучаемые на всех тенантах | Команда ML | Только модели; результаты модели возвращаются в области применения тенанта |
k-анонимность для агрегатов тенантам
При предоставлении кросс-тенантной аналитики тенанту (например, «как ваша конверсия сравнивается с медианой платформы»):
- Минимальное число тенантов в агрегате:
k_min_tenants(типично 5). - Минимальное число событий в каждом тенанте:
k_min_events(типично 100). - Если меньше — агрегат не возвращается; вместо этого возвращается ответ «недостаточно данных для сравнения».
Это защищает от ре-идентификации малых тенантов в агрегатах.
Журнал аудита кросс-тенантных запросов
Все кросс-тенантные запросы (от команды платформы или от тенантов через программный интерфейс аналитики) журналируются в audit log:
- Кто запросил.
- Когда.
- Какой запрос (с параметрами).
- Какой ответ (метрики результата, не сами строки).
Журнал доступен:
- Для внутреннего ревью раз в квартал (compliance review).
- Для регулятора при запросе.
- Для тенанта — на свои собственные запросы.
Ограничение цели и политика хранения
Ограничение цели (purpose limitation)
По принципу общего регулирования защиты данных — данные собираются и хранятся только для определённой цели. Каждое событие в момент захвата помечается целью использования (purpose):
| Цель | Описание | Какие данные требуются |
|---|---|---|
service_delivery | Предоставление услуги конечному клиенту | Полная необходимая информация для бронирования |
partner_billing | Биллинг партнёра по фактическому потреблению | Метрики потребления, без поведенческих следов конечных клиентов |
platform_analytics | Внутренняя аналитика платформы | Агрегаты + поведенческие следы с анонимизацией |
ml_training | Обучение ML-моделей платформы | Поведенческие данные с анонимизацией |
partner_facing_analytics | Аналитический продукт для партнёров (тарифы Professional, Enterprise) | Агрегаты с k-анонимностью |
compliance_audit | Хранение для регулятора (audit trail) | Минимально необходимое; долгосрочно |
security_incident | Расследование инцидентов безопасности | Технические следы; ограниченное по времени хранение |
Каждое поле в DWH доступно только для целей, для которых оно было захвачено. Запрос аналитики, требующий поля, не разрешённого для текущей цели, отбрасывается на уровне query layer.
Политика хранения (retention policy)
Срок хранения определяется классом хранения (retention_class):
| Класс | Срок хранения | Применимость |
|---|---|---|
tx_audit | 7 лет | Транзакционные события (платежи, бронирования) — для соответствия фискальным требованиям |
compliance_log | 10 лет | Журнал согласия (consent log), журнал доступа к персональным данным |
behavioral_long | 25 месяцев | Поведенческие данные для долгосрочной аналитики (типичный максимум по общему регулированию защиты данных) |
behavioral_short | 13 месяцев | Поведенческие данные для краткосрочной операционной аналитики |
system_metric | 13 месяцев | Системные метрики (производительность, инциденты) |
aggregate_long | Бессрочно | Агрегированные данные без PII |
temp_processing | 30 дней | Временные данные для текущей обработки |
После истечения срока хранения данные физически удаляются из DWH (DROP partition). Это автоматический процесс, журналируется. Ручное удлинение срока запрещено — изменение политики возможно только через согласованный процесс с фиксацией в реестре политик.
Право быть забытым (right to be forgotten)
При запросе на удаление от субъекта данных (по общему регулированию защиты данных):
- Поиск всех записей с этим
actor_hash(если соль ротируется регулярно — поиск по нескольким текущим солям). - Удаление или анонимизация в operational layer.
- В DWH — анонимизация (замена
actor_hashна специальный «forgotten» хеш) с сохранением агрегационной целостности. - Журнал удаления — для доказательства регулятору.
Подробности — в Соответствие требованиям регуляторов.
Поток обработки данных и потоковая обработка
Архитектурные слои обработки
[Источники] → [Bronze layer] → [Silver layer] → [Gold layer] → [Потребители]
События Сырой Очищенный Агрегаты,
захват + обогащение готовые витрины
Бронзовый слой (bronze layer) — сырой захват
- Все аналитические события записываются как есть, после анонимизации на ingestion.
- Партиционирование по времени и тенанту.
- Срок хранения — типично 30–90 дней.
- Используется как источник для re-processing при изменении логики обработки.
Серебряный слой (silver layer) — очищенный и обогащённый
- Дедупликация по
event_id. - Обогащение измерениями (lookup в
dim_*таблицы). - Обогащение производными атрибутами (например,
is_first_session_for_actor,time_since_last_event). - Партиционирование как в бронзовом слое.
- Срок хранения — по
retention_classкаждого события.
Золотой слой (gold layer) — агрегаты и витрины
- Готовые таблицы фактов с агрегациями за день/час.
- Готовые витрины для конкретных потребителей (отчёты, дашборды, ML feature store).
- Срок хранения — долгий или бессрочный (агрегаты не несут PII).
Real-time vs batch обработка
Real-time (streaming) — для событий, требующих мгновенной обработки:
- Системные метрики и инциденты (наблюдаемость).
- Метрики тарификации в реальном времени (учёт потребления).
- Сигналы для ML-моделей с быстрым обновлением (anti-fraud, dynamic pricing).
- Алерты по аномалиям.
Batch — для остального:
- Дневная/часовая агрегация в gold layer.
- Долгосрочная аналитика.
- Обучение ML-моделей (training).
Технологический выбор по фазам
| Фаза | Bronze layer | Silver layer | Gold layer / DWH | Real-time |
|---|---|---|---|---|
| Bootstrap | PostgreSQL отдельная схема | PostgreSQL views | PostgreSQL агрегаты | Простой polling |
| 2 (Production) | Object Storage (Parquet) | Управляемый ETL (managed pipeline) | Управляемый ClickHouse / OpenSearch для аналитики | Управляемый Kafka + streaming consumer |
| 3 (ML & analytics) | Object Storage с Lake-форматом (Delta / Iceberg) | Spark / Flink streaming | Snowflake / BigQuery / отдельный ClickHouse кластер | Расширенный streaming |
| 4 (Multi-region) | Multi-region Object Storage | Federated processing | Multi-region DWH с репликацией | Multi-region Kafka |
Конкретный выбор технологий — открытая развилка, эскалируется при выходе с фазы Bootstrap.
Закрытие технического долга 8
В Связь с реализацией → «Долг 8. Mixed domain и analytical events в events_themes» зафиксировано:
- Текущее состояние: схема
events_themes(DDL 2026-04-24) — единое хранилище для разных типов событий (доменных и аналитических смешанно). - Целевое состояние: разделение на
domain_eventsчерез event bus +analytical_eventsчерез tracking pipeline в DWH.
План миграции
Этап 1. Параллельный захват (фаза Bootstrap → 2)
- Развернуть tracking pipeline и DWH (фаза 2).
- Все новые события писать параллельно в
events_themes(как раньше) и в новый pipeline. - Период проверки — 2–3 месяца, сравнение данных.
Этап 2. Переключение потребителей (фаза 2)
- Аналитические потребители переключаются на новый DWH.
- Доменные потребители переключаются на event bus (Managed Kafka).
events_themesостаётся как fallback ещё 1–2 месяца.
Этап 3. Архивирование старой схемы (фаза 3)
events_themesпомечается как deprecated.- Содержимое экспортируется в архивное хранилище для compliance.
- Схема удаляется из активного использования.
Запрет на возврат к смешанной схеме
После завершения миграции — запрет на возврат к единому хранилищу. Это закрепляется как архитектурное правило, проверяется на каждом ревью.
Партнёрский продукт аналитики
Платформа предоставляет тенантам тарифа Professional и выше партнёрский продукт аналитики (partner-facing analytics product):
Что доступно
- Свои метрики потребления (вызовы, бронирования, конверсия).
- Свои метрики экономики (стоимость по тарифу, прогноз счёта).
- Кросс-тенантные агрегаты для бенчмаркинга (с k-анонимностью).
- Воронка от поиска до бронирования.
- Качество поиска (CTR, доля отказов).
Как доступно
- Дашборды в партнёрской консоли (см. Программный интерфейс как продукт).
- Программный интерфейс аналитики (analytics API) для партнёров, желающих интегрировать в собственные системы.
- Экспорт данных (data export) — выгрузка в формате CSV / Parquet для партнёров с большим объёмом (только тариф Enterprise).
Свежесть данных
- Real-time метрики (метрики потребления, текущие вызовы) — задержка десятки секунд.
- Дневные агрегаты — задержка часы (готовы на следующий день).
- Длинные метрики (тренды) — задержка дни (еженедельная пересборка).
События платформы данных
Слой захвата событий и хранилища данных публикует операционные события (для собственного контура наблюдаемости):
| Событие | Когда | Главные потребители |
|---|---|---|
tracking.batch.received | При приёме батча событий на ingestion | Контур наблюдаемости |
tracking.batch.validated | После валидации схемы | Контур наблюдаемости |
tracking.event.dropped | При отбрасывании события (схема, rate limit, дубликат) | Контур наблюдаемости, для аномалий — алерты |
dwh.partition.materialized | После материализации партиции в gold layer | Контур аналитики |
dwh.retention.executed | После выполнения политики хранения (удаление партиций) | Контур compliance |
dwh.privacy.anonymized | После анонимизации по запросу права быть забытым | Контур compliance |
analytics.query.executed | После выполнения аналитического запроса | Контур аудита |
Фазы развёртывания
Фаза Bootstrap (0–6 месяцев)
Что разворачивается:
- Каноничная модель
AnalyticalEventзафиксирована. - Простой tracking endpoint в основной службе платформы.
- Хранение в отдельной схеме PostgreSQL (не в
events_themesсмешанной). - Реестр схем в виде набора JSON Schema файлов в репозитории.
- Базовая анонимизация на захвате.
- Простые дашборды через Grafana.
Триггер выхода:
- Объём событий превышает 10 миллионов в день.
- Появляются первые партнёрские запросы на аналитический продукт.
Фаза 2 — Production analytics (6–18 месяцев)
Что разворачивается:
- Управляемый Kafka для tracking pipeline отдельно от event bus.
- Управляемый ClickHouse или аналог как DWH-движок.
- Потоковая обработка (streaming) для real-time метрик.
- Полная политика хранения с автоматическим жизненным циклом партиций.
- Партнёрский продукт аналитики для тарифа Professional.
- Audit log кросс-тенантных запросов.
- Запуск миграции с
events_themes(этапы 1–2 закрытия долга 8).
Триггер выхода:
- Готовность к обучению ML-моделей на данных платформы.
- Расширение в новые регионы — нужны региональные требования к локализации данных.
Фаза 3 — ML и расширенная аналитика (18–30 месяцев)
Что разворачивается:
- Lake-формат (Delta или Iceberg) на Object Storage.
- Spark или Flink для серьёзной streaming-обработки.
- ML feature store, интегрированный с DWH (см. Платформа машинного обучения, фаза 3).
- Партнёрский программный интерфейс аналитики.
- Экспорт данных для тарифа Enterprise.
- Завершение миграции с
events_themes(этап 3).
Фаза 4 — Многорегиональная зрелость (30+ месяцев)
Что разворачивается:
- Многорегиональный DWH с репликацией.
- Локализация данных по регионам (data residency) для регуляторных требований.
- Federated query layer — запросы по нескольким регионам.
- Snowflake или BigQuery как опция для крупнейших партнёров.
Архитектурные решения с тезисным обоснованием
Решение 1. Разделение доменных и аналитических событий — архитектурный закон
Цель: обеспечить операционную целостность доменного контура и аналитическую гибкость аналитического контура одновременно.
Тезисы:
- Доменные события — основа операционных контуров (booking, payment). Их потеря или дублирование ведёт к финансовым ошибкам.
- Аналитические события — основа маркетинговой и продуктовой аналитики. Их строгие гарантии не нужны, а гибкость схемы критична.
- Современные платформы верхнего уровня (Stripe, Twilio, Algolia) разделяют эти классы как стандарт.
- Это закреплено в Ось данных и интеллекта как главный принцип.
Альтернатива: единая шина событий для обоих классов. Отклонено: либо теряется операционная целостность, либо раздувается стоимость хранения и операционная нагрузка.
Принимаемые компромиссы:
- Дублирование инфраструктуры (две шины, два хранилища). Это часть архитектуры, не накладные расходы.
- Согласование между классами требует дисциплины — событие не должно дублироваться в обоих классах без обоснования.
Решение 2. Каноничная схема аналитического события с реестром схем
Цель: обеспечить эволюцию схемы без ломающих изменений и согласованную обработку всеми потребителями.
Тезисы:
- Аналитические события собираются из множества поверхностей разными командами (frontend, backend, партнёрские SDK). Без формальной схемы — хаос.
- Реестр схем с версионированием — стандарт индустрии (Confluent Schema Registry paradigm, AWS Glue Schema Registry paradigm).
- Без реестра невозможно безопасно эволюционировать аналитику — каждое изменение требует ревью и блокирует команды.
Решение 3. Анонимизация при захвате, не позже
Цель: минимизировать blast-радиус утечки и упростить compliance.
Тезисы:
- Если PII попадает в DWH в неанонимизированном виде — весь DWH становится PII-системой со всеми обязательствами.
- Анонимизация при захвате означает: даже при компрометации DWH персональные данные не утекут.
- Common Architecture Practices (Stripe, Twilio) — все так делают.
Принимаемые компромиссы:
- Невозможность восстановить исходные данные. Это design choice, не недостаток.
- Сложность реализации права быть забытым (требует ротации соли). Решается процессом.
Решение 4. Звёздная схема в DWH с медленно меняющимися измерениями
Цель: обеспечить корректный исторический контекст для аналитики и совместимость с большинством BI-инструментов.
Тезисы:
- Звёздная схема — стандарт DWH со времени Кимбола. Все BI-инструменты её понимают.
- Тип 2 медленно меняющихся измерений — единственный корректный способ обрабатывать исторические тарифы партнёров и подобное.
- Без типа 2 финансовая отчётность неточна (факт привязан к текущему атрибуту, не историческому).
Решение 5. Классы приватности и политика хранения как первоклассные сущности схемы
Цель: сделать соответствие нормативам автоматическим, не процессом.
Тезисы:
- Если приватность — это процесс ревью, она ломается под давлением. Если архитектурно — она работает.
- Каждое поле помечено классом приватности и классом хранения в момент создания. Изменение требует процесса.
- Политика хранения автоматически удаляет старые данные — без человеческого вмешательства.
Открытые развилки
Развилка 1. Конкретный движок DWH
OpenSearch / ClickHouse / Snowflake / BigQuery / Druid — выбор движка зависит от профиля нагрузки и стоимости. На фазе 2 — управляемый ClickHouse как разумный baseline; на фазе 3 — может потребоваться расширение или замена.
Эскалируется: при подготовке к фазе 2 (Production analytics).
Развилка 2. Конкретные сроки хранения внутри классов
behavioral_long — 25 месяцев максимум по общему регулированию защиты данных (типичная норма). Конкретный срок внутри допустимого диапазона зависит от бизнес-потребностей.
Эскалируется: при создании детальной таблицы политик с привязкой к конкретным метрикам.
Развилка 3. Партнёрский экспорт данных — формат и канал доставки
Для тарифа Enterprise возможен экспорт сырых поведенческих данных партнёру (с анонимизацией). Конкретный формат (CSV / Parquet / JSON) и канал доставки (S3 share / SFTP / managed API) — открыто.
Эскалируется: при появлении первых корпоративных партнёров с запросом на экспорт.
Развилка 4. Платформа экспериментов A/B — единая или раздельная
Платформа A/B-экспериментов (см. Платформа A/B-тестирования, фаза 4) использует часть инфраструктуры платформы данных. Развилка — насколько она самостоятельна или встроена.
Эскалируется: при создании документа A/B-платформы.
Развилка 5. Real-time ML feature serving — архитектурный путь
ML-модели платформы могут потреблять данные либо через периодическую выборку из DWH (фаза 3 baseline), либо через real-time feature store, обновляемый из streaming pipeline (фаза 4). Выбор зависит от ML-профиля и стоимости.
Эскалируется: при создании Платформа машинного обучения.
Связанная документация
Корневые архитектурные документы
- Ось данных и интеллекта — пять компонентов оси, главные принципы. Этот документ детализирует компоненты 1 и 2.
- Манифест переосмысления — обязательство закладывать data infra с нулевого дня.
- Каноничная доменная ось — каноничные сущности, события которых попадают в DWH через измерения.
- Архитектурный якорь и бизнес-модель — динамическая тарификация на основе метрик из DWH.
- Связь с реализацией — Долг 8, который закрывается этим документом.
- Операционная ось — наблюдаемость платформы данных.
Связанные доменные документы
- Соответствие требованиям регуляторов — § 11.6 «Влияние на data-platform-and-events-tracking, ml-platform».
- Хранение — DWH как отдельный класс хранилища.
- Тенантная идентичность и изоляция — изоляция данных по тенанту.
- Программный интерфейс как продукт — партнёрский продукт аналитики.
- Платёжный домен — события платежей в DWH.
- Поиск и обнаружение — события поиска в DWH.
- Учёт потребления и квоты — метрики тарификации из DWH.
- Технологический фундамент реализации — управляемый Kafka, управляемый ClickHouse как baseline.
- Событийная шина и асинхронная дисциплина — отдельная шина для доменных событий.
- Первоначальная таксономия событий — связь с доменной таксономией (но не пересечение).
Документы развития
- Скелеты AsyncAPI и event envelopes — формальная спецификация асинхронных контрактов, переиспользуется для аналитической таксономии.
- Реестр ломающих изменений — правила эволюции схем, переиспользуются для реестра схем аналитики.
- Каталог каналов событий — каналы доменных событий.
Операционная сторона
- Наблюдаемость и реагирование на инциденты — наблюдаемость платформы данных.
- Дорожная карта инфраструктурного масштабирования — фазы развёртывания инфраструктуры данных.
Архитектурные правила
- Закон 00000 — платформа главенствует над поставщиками — каноничная аналитическая модель не зависит от форматов поставщиков.
- Современные лучшие практики верхнеуровневых платформ — Stripe, Algolia, Cloudflare как ориентиры.
- Развитие без деградации — фазы как расширение, не миграция.
- Эластичное масштабирование и упаковка по фазам — фазы развёртывания платформы данных.
- Тезисное обоснование архитектурных решений — формат принятия решений.
Уточнение под Фазы 5–6 (28.04.2026) — связь с booking state machine, isolation, security, DR
Документ опубликован 26.04.2026 в Фазе 4. После Фаз 5–6 (caнoничные углубления и операционная зрелость) платформа данных получила новые потоки событий и обязательств, которые должны быть явно зафиксированы для интеграции потребителями.
Связь со статусной машиной бронирования
reference/booking-state-machine.md (Фаза 5) фиксирует 14 каноничных состояний Booking. Каждое transition генерирует доменное событие:
booking.created(state:draft);booking.submitted(state:submitted);booking.revalidation_started(state:pending_revalidation);booking.supplier_confirmation_started(state:pending_supplier_confirmation);booking.supplier_confirmed(state:supplier_confirmed);booking.platform_confirmed(state:platform_confirmed);booking.partially_confirmed(state:partially_confirmed);booking.unknown_external_state(state:unknown_external_state) — критическое событие, target SLI менее 1%;booking.failed(state:failed);booking.cancel_requested,booking.cancel_in_progress,booking.cancelled;booking.amendment_in_progress;booking.completed.
Все эти события — доменные события (domain events) с persistent journal, не аналитические. Они являются источниками истины для downstream consumers (operational dashboards, billing, compliance audit, SLA measurement).
booking_state_transition table — отдельный canonical persistent log в Tier 1 storage class (см. database-schema.md).
Связь с saga Tour Builder
reference/tour-builder-operational-model.md (Фаза 5) генерирует saga events:
tour.composition.created;tour.composition.rule_violation_detected;tour.booking_transaction.started;tour.booking_transaction.compensation_triggered;tour.drift.detected;tour.drift.resolved;tour.proposal.published;tour.proposal.shared;tour.proposal.viewed;tour.proposal.accepted_for_conversion.
Saga events — гибрид domain + analytical: persistent для transaction integrity, но также используются для analytics (accepted_for_conversion rate, drift frequency per supplier).
Связь с уровнями тенантной изоляции и k-anonymization
reference/multi-tenant-isolation-strength.md (Фаза 5) определяет 3 уровня изоляции, прямо влияющие на платформу данных:
logical— события всех tenants в общем DWH, partitioned bytenant_id, RLS policies на queries;dedicated_compute— отдельный DWH namespace per tenant, или схема в shared cluster;dedicated_infrastructure— отдельный DWH cluster per tenant (Enterprise mandatory для regulated).
Cross-tenant aggregation rules:
- запрос с агрегацией по нескольким тенантам — минимальный размер группы k=10 (k-anonymity);
- если cohort менее k — запрос отклоняется или возвращается с suppressed values;
- audit log каждого cross-tenant aggregation request (включая identity делавшего запрос).
IsolationBoundaryCheck (continuous automated проверка) — отдельный канал событий:
isolation.check.started,isolation.check.completed,isolation.check.breach_detected;- target: 0 successful breaches за rolling 90 дней.
Связь с security architecture и audit logging
reference/security-architecture.md (Фаза 10) фиксирует canonical audit log как immutable storage (WORM-grade). Audit events — отдельный класс между domain и analytical:
Каноничные security/audit events:
auth.login.success,auth.login.failed,auth.mfa.required,auth.mfa.success,auth.mfa.failed;auth.token.issued,auth.token.revoked,auth.session.expired;authz.action.executed,authz.action.denied,authz.privilege.escalated;data.sensitive.accessed(PII access — обязательно для GDPR);data.exported(bulk export — для exfiltration monitoring);data.cross_tenant.attempted;admin.user.created,admin.role.modified,admin.config.changed;admin.secret.rotated,admin.secret.revoked;security.suspicious_activity.detected,security.brute_force.detected,security.data_breach.detected.
Audit log — отдельный pipeline, не смешивается с analytical events. Retention 7 лет (Tier 1), tamper detection через hash chains, доступ только через explicit roles.
Связь со SLA измерением
operations/sla-and-on-call-model.md (Фаза 6) использует data platform для измерения SLI:
Каноничные SLI metrics, источник — data platform:
- availability per surface (на основе analytical event
request_received+ status code); - latency p95 (на основе
request_completedevents); - webhook delivery (на основе
webhook.delivery.attempted/webhook.delivery.completed); - search freshness (на основе search response cache age);
- booking confirmation latency (на основе booking state transitions);
unknown_external_stateratio (на основе booking state events);- payment success rate (на основе payment events);
- restoration success rate (на основе DR events — см. ниже);
- MTTR (на основе incident events);
- support response time (на основе support ticket events).
Data platform — базовая инфраструктура для SLI/SLO measurement; без неё SLA — формальное обещание без измерения.
Связь с DR и capacity events
operations/disaster-recovery-and-capacity.md (Фаза 6) генерирует отдельный класс операционных событий:
DR events:
dr.recovery.declared,dr.recovery.point_selected,dr.recovery.restored_to_staging;dr.recovery.smoke_tests_passed,dr.recovery.promoted_to_production,dr.recovery.completed;dr.recovery.postmortem_completed;dr.backup.created,dr.backup.verified,dr.backup.expired;dr.drill.scheduled,dr.drill.started,dr.drill.completed_successful,dr.drill.completed_with_issues,dr.drill.failed.
Capacity events:
capacity.forecast.created,capacity.forecast.updated;capacity.threshold.warning_triggered,capacity.threshold.critical_triggered;capacity.provisioning.requested,capacity.provisioning.completed;capacity.degradation.activated,capacity.degradation.deactivated.
Эти события — operational class между domain и analytical: persistent для audit, но также используются для capacity forecasting и SLA reports.
Связь с runbooks и incident events
operations/runbooks-incident-playbooks.md (Фаза 6) генерирует:
incident.detected,incident.runbook.started,incident.runbook.step_completed;incident.escalated,incident.resolved;incident.postmortem.scheduled,incident.postmortem.completed;incident.action_item.created,incident.action_item.resolved.
Incident events — operational class, retention в audit log (7 лет для regulated incidents).
Связь с compliance событиями
reference/compliance-and-legal.md (Фаза 4) определяет:
compliance.dsr.received(Data Subject Request);compliance.dsr.responded;compliance.consent.collected,compliance.consent.withdrawn;compliance.retention.cleanup_executed;compliance.breach.detected,compliance.breach.notified;compliance.dpa.signed;compliance.audit.started,compliance.audit.completed.
Compliance events — regulatory class, обязательны для GDPR audit trail.
Каноничный итог уточнения
Платформа данных и events tracking теперь интегрирована со всеми операционными доменами Фаз 5–6:
| Класс events | Источник | Storage | Retention |
|---|---|---|---|
| Domain events (caнoничные state transitions) | сервисы | event log + transactional layer | долгий (audit) |
| Analytical events (поведение) | поверхности взаимодействия | DWH (ClickHouse/PostgreSQL) | class-зависимый |
| Saga events (Tour Builder) | tour-builder-service | гибрид event log + DWH | долгий |
| Audit events (security) | все services | immutable WORM storage | 7 лет (Tier 1) |
| Operational events (DR, capacity, incidents) | runbooks, capacity service, DR service | event log + DWH | долгий (regulated) |
| Compliance events (GDPR/audit) | compliance pipeline | immutable audit log | 7+ лет |
Все классы потребляют общую infrastructure (event bus, schema registry, retention enforcement), но имеют разные guarantees и разные access controls.
При создании контрактов consumers — использовать каноничные имена событий из специализированных документов (см. ссылки выше), не «придумывать локально».
Уточнение выполнено через no-destruction.