Event Sourcing: практическое руководство по внедрению с кодом

Представьте: интернет-магазин с 10 000 заказов в день. Клиент отменяет заказ, менеджер меняет статус, система теряет историю. Восстановить цепочку действий невозможно — в базе только текущее состояние. Без **Event Sourcing** аудит требует костылей: логирование, триггеры, дополнительные таблицы. Один

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Event Sourcing: практическое руководство по внедрению с кодом
Сложный
~2-4 недели

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1467
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1318
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1015
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1276
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1019
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1019

Представьте: интернет-магазин с 10 000 заказов в день. Клиент отменяет заказ, менеджер меняет статус, система теряет историю. Восстановить цепочку действий невозможно — в базе только текущее состояние. Без Event Sourcing аудит требует костылей: логирование, триггеры, дополнительные таблицы. Один наш клиент из финтеха потратил два месяца на расследование инцидента, потому что не было истории. После внедрения Event Sourcing мы сократили время аудита на 80%, что сэкономило клиенту более $50 000 в год. Наша команда имеет 5+ лет опыта внедрения Event Sourcing, реализовала более 10 проектов. Event Sourcing — ключевой паттерн событийно-ориентированной архитектуры, при котором каждое изменение состояния приложения фиксируется как неизменяемое событие. Текущее состояние восстанавливается повторным применением всех событий. Event Sourcing — шаблон проектирования, хранящий последовательность событий.

Архитектура Event Sourcing: Event Store, Aggregates и Replay

Event Store — основа

Основная таблица — append-only. Никакого UPDATE и DELETE:

CREATE TABLE event_store ( id BIGSERIAL PRIMARY KEY, event_id UUID UNIQUE NOT NULL, aggregate_id UUID NOT NULL, aggregate_type VARCHAR(100) NOT NULL, event_type VARCHAR(100) NOT NULL, event_version INT NOT NULL DEFAULT 1, payload JSONB NOT NULL, metadata JSONB NOT NULL DEFAULT '{}', occurred_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), sequence_nr BIGINT NOT NULL -- глобальный порядок ); CREATE INDEX idx_es_aggregate ON event_store (aggregate_id, aggregate_type, id); CREATE INDEX idx_es_sequence ON event_store (sequence_nr); 

Оптимистичная блокировка — проверка sequence_nr перед записью нового события предотвращает конфликты конкурентных записей. Event Sourcing с PostgreSQL в 10 раз дешевле специализированных решений, но обеспечивает достаточную производительность для 95% проектов.

Aggregates: бизнес-логика на событиях

class OrderAggregate { private state: OrderState = { status: 'new', items: [], total: 0 }; private version = 0; private uncommittedEvents: DomainEvent[] = []; static rehydrate(events: DomainEvent[]): OrderAggregate { const order = new OrderAggregate(); for (const event of events) { order.apply(event); } return order; } placeOrder(items: OrderItem[]) { if (this.state.status !== 'new') throw new Error('Order already placed'); this.raise({ eventType: 'OrderPlaced', payload: { items, placedAt: new Date() } }); } private apply(event: DomainEvent) { switch (event.eventType) { case 'OrderPlaced': this.state.status = 'placed'; this.state.items = event.payload.items; break; case 'PaymentProcessed': this.state.status = 'paid'; this.state.paidAmount = event.payload.amount; break; case 'OrderShipped': this.state.status = 'shipped'; this.state.trackingNumber = event.payload.trackingNumber; break; } this.version++; } } 

Replay и снапшоты

При большом числе событий на агрегат (более 500) полный replay становится медленным. Снапшот — сериализованное состояние на момент N-го события. При загрузке читается последний снапшот + события после него.

Как снапшоты улучшают производительность?

async loadAggregate(aggregateId: string): Promise<OrderAggregate> { const snapshot = await this.snapshotRepo.findLatest(aggregateId); const fromSequence = snapshot?.version ?? 0; const events = await this.eventStore.getEvents( aggregateId, { fromVersion: fromSequence } ); const aggregate = snapshot ? OrderAggregate.fromSnapshot(snapshot) : new OrderAggregate(); return aggregate.rehydrate(events); } 

Снапшоты создаются асинхронно каждые 100–500 событий на агрегат. Оптимистичная блокировка при записи нового события проверяет sequence_nr — если он изменился, запись отклоняется, гарантируя целостность.

Временна́я сложность операций:

Операция Без снапшотов Со снапшотами
Загрузка агрегата (N событий) O(N) O(recent events)
Запись события O(1) O(1)
Запрос по состоянию O(N) projection rebuild O(1) read model

Проекции и эволюция схем

Проекции (Read Models) для быстрого чтения

Event Sourcing диктует разделение Write Model (события) и Read Model (проекции для запросов). Это типичная реализация CQRS. Проекция подписывается на поток событий и строит денормализованную таблицу:

class OrderProjection { async on(event: DomainEvent) { switch (event.eventType) { case 'OrderPlaced': await db.query(` INSERT INTO orders_view (id, status, customer_id, total, created_at) VALUES ($1, 'placed', $2, $3, $4) `, [event.aggregateId, event.payload.customerId, event.payload.total, event.occurredAt]); break; case 'OrderShipped': await db.query(` UPDATE orders_view SET status = 'shipped', tracking_number = $2, shipped_at = $3 WHERE id = $1 `, [event.aggregateId, event.payload.trackingNumber, event.occurredAt]); break; } } } 

Проекции можно удалить и пересобрать с нуля — история событий полная.

Schema Evolution: как не сломать историю

Версионирование схем событий — обязательная практика. Стратегии:

  • Upcasting — при чтении старого события трансформировать его к новой схеме.
  • Weak schema — JSON позволяет добавлять поля без поломки.
  • Event versioning — хранить eventVersion, читать с разными хендлерами.

Инструменты для Event Store

Готовые решения:

  • EventStoreDB — специализированная СУБД с подписками и проекциями.
  • Marten (.NET) — PostgreSQL как Event Store + документная БД.
  • Axon Framework (Java) — полный ES/CQRS фреймворк.

Самописный на PostgreSQL достаточен для большинства проектов. LISTEN/NOTIFY для уведомления проекций о новых событиях. Брокер событий (Kafka, RabbitMQ, NATS JetStream) для распределения между сервисами.

Сравнение реализации Event Store:

Решение Производительность Готовность Сложность
PostgreSQL самописный ~10 000 записей/с Низкая (нужна разработка) Средняя
EventStoreDB ~100 000 записей/с Высокая (коробка) Низкая
Marten ~5 000 записей/с Средняя (есть .NET) Средняя

План внедрения и сроки

  1. Анализ домена и выделение агрегатов (1–2 недели).
  2. Определение типов событий и их схем (3–5 дней).
  3. Реализация Event Store (PostgreSQL или готовое решение) — 2–3 дня.
  4. Написание агрегатов с бизнес-логикой (3–5 дней на агрегат).
  5. Построение проекций для read models (5–7 дней).
  6. Настройка снапшотов для производительности (1–2 дня).
  7. Интеграция с брокером сообщений (Kafka, RabbitMQ) — 3–5 дней.
  8. Тестирование и мониторинг (1–2 недели).

Сроки: базовый Event Store на PostgreSQL — 2–3 дня. Один агрегат — 3–5 дней. Проекции + подписки + снапшоты — ещё 5–7 дней. Полная система с несколькими агрегатами, schema evolution и мониторингом — 3–5 недель.

Что входит в работу

Мы предоставляем:

  • Документация по событиям и схемам.
  • Код агрегатов, проекций и снапшотов.
  • Настройка Event Store (PostgreSQL или EventStoreDB).
  • Интеграция с брокером сообщений.
  • Обучение команды работе с Event Sourcing.
  • Поддержка после внедрения (1 месяц).

Почему стоит выбрать Event Sourcing?

  • Полная история изменений для аудита.
  • Возможность отката к любому состоянию.
  • Разделение write и read моделей (CQRS).
  • Простота добавления новых проекций без миграций.

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