> Кто принимал решения по архитектуре сервиса лояльности (Go)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: BetBoom

Стек: Go

> Пример ответа

Короткий ответ

Архитектурные решения по сервису лояльности принимались коллегиально: технический лидер и архитектор задавали общий каркас, а детали проектирования модулей, API-контрактов и схем данных обсуждались на архитектурных ревью с участием всей команды. Финальное слово оставалось за tech lead, но учитывались мнения senior-разработчиков и продуктового менеджера. Для критичных решений (например, выбор хранилища или способа интеграции) проводился формальный ADR-процесс.

Подробное объяснение

В типичном сервисе лояльности архитектурные решения распределяются по уровням:

  • Глобальная архитектура (микросервис vs монолит, event-driven vs request-response) - решает архитектор совместно с tech lead, учитывая стратегию компании и существующий ландшафт.
  • Детальное проектирование (структура модулей, интерфейсы, работа с бонусными баллами, антифрод-проверки) - ответственность senior-разработчиков, которые предлагают варианты и защищают их на ревью.
  • Инфраструктурные решения (БД, очереди, кэши) - совместно с DevOps/SRE, но с приоритетом мнения команды разработки.
  • Продуктовые компромиссы (например, когда списывать баллы: сразу или после подтверждения заказа) - согласуются с product owner, но техническую реализацию предлагает backend.

На практике важно, чтобы решения фиксировались в ADR (Architecture Decision Records) - это позволяет вернуться к контексту и не пересматривать их без веской причины.

На практике

В моём опыте процесс выглядел так:

  1. Инициация - задача формулируется на уровне эпика, выделяется технический спонсор (обычно senior или tech lead).
  2. Исследование - спонсор готовит 2-3 варианта решения с оценкой trade-off: сложность, стоимость, время, риски.
  3. Архитектурное ревью - встреча 30-60 минут, где команда задаёт вопросы, предлагает альтернативы. Решение принимается голосованием, но veto у tech lead.
  4. Документирование - короткий ADR на 1-2 страницы: контекст, решение, последствия.
  5. Реализация - после принятия решения разработка идёт по утверждённому плану, отклонения возможны только через новый ADR.

Для сервиса лояльности особенно важны решения по:

  • Консистентности данных - баллы должны начисляться атомарно с заказом, поэтому часто выбирают транзакционную БД (PostgreSQL) + outbox pattern для событий.
  • Масштабированию - если сервис обрабатывает миллионы операций, нужен шардинг по user_id или отдельное хранилище для балансов.
  • Идемпотентности - повторные запросы от клиентов не должны начислять баллы дважды.

Пример кода

GO
// Пример ADR-подхода: выбор между синхронным и асинхронным начислением баллов
// Вариант 1: синхронное начисление в транзакции заказа
func (s *Service) CreateOrder(ctx context.Context, order Order) error {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback()
if err := s.repo.InsertOrder(ctx, tx, order); err != nil {
return err
}
if err := s.loyaltyRepo.AddPoints(ctx, tx, order.UserID, order.Total*0.05); err != nil {
return err
}
return tx.Commit()
}
// Вариант 2: асинхронное начисление через outbox
func (s *Service) CreateOrder(ctx context.Context, order Order) error {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback()
if err := s.repo.InsertOrder(ctx, tx, order); err != nil {
return err
}
// пишем событие в outbox, обработчик начислит баллы
if err := s.outbox.Publish(ctx, tx, "order.created", order); err != nil {
return err
}
return tx.Commit()
}

Как отвечать на собеседовании

  • Начните с того, что решения не принимаются единолично - это командный процесс с чёткой ответственностью.
  • Приведите конкретный пример из практики: опишите задачу, варианты, критерии выбора и итог.
  • Покажите, что умеете защищать решение: назовите trade-off, которые взвешивали.
  • Упомяните ADR - это сильный сигнал зрелости процесса.
  • Если спросят про конфликт мнений - расскажите, как разрешали: данные, прототип, нагрузочное тестирование.
  • Не говорите "решал я" - это выглядит некомандно. Лучше: "я предложил, команда согласовала, tech lead утвердил".

Что проверяет интервьюер

  • Умение работать в команде - не единоличник ли вы, учитываете ли чужое мнение.
  • Понимание архитектурных trade-off - можете ли обосновать выбор, а не просто перечислить технологии.
  • Наличие практического опыта - реальные кейсы, а не теория.
  • Уровень ответственности - берёте ли на себя инициативу или ждёте указаний.
  • Знание процессов - ADR, ревью, документирование решений.

Типичные ошибки

  • "Я решал всё сам" - красный флаг для senior-позиции, выглядит как неумение работать в команде.
  • Нет конкретики - "мы обсуждали и решили" без деталей: какие варианты, почему выбрали этот.
  • Игнорирование бизнес-контекста - решение только с технической стороны, без учёта стоимости и сроков.
  • Не упоминаете документацию - если нет ADR, значит решения не фиксируются и не пересматриваются.
  • Путаница ролей - не различаете, кто отвечает за глобальную архитектуру, а кто за детали модулей.
  • Не готовы к критике - если не можете объяснить недостатки выбранного решения, значит не до конца его понимаете.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью