Главная/Проекты/Скорость и непрерывность продаж
SFA Производительность Непрерывность бизнеса B2B-портал

Скорость и непрерывность продаж в SFA-системе FMCG-производителя

Через мобильное приложение торговых представителей ежедневно проходят заказы больше чем на 100 млн ₽. Ускорили синхронизацию, каталог и поиск и сделали так, чтобы заказы доходили до дистрибьютора даже при сбое связи или дата-центра.

  • В 5,2 раза — в среднем быстрее синхронизация мобильного приложения
  • В 10 раз — легче изображения товаров в каталогах
  • 80 → 20 минут — индексация каталога товаров с промо
Заглавное фото
Клиент
ОтрасльFMCG, производство
МасштабЗаказы на 100+ млн ₽ в день через мобильное приложение
географияРоссия
ФорматОптимизация производительности и сценарий непрерывности бизнеса
02
Контекст

Клиент и исходная ситуация

Клиент — международный FMCG-производитель. GROTEM развивает его экосистему продаж: мобильное SFA-приложение торговых представителей, B2B-портал и телепродажи. Через мобильное приложение каждый рабочий день берутся заказы чуть больше чем на 100 млн ₽.

При таком обороте любой сбой — это прямые потери выручки производителя и дистрибьюторов, а медленное приложение отнимает время визита у представителя и клиента.

ОтрасльFMCG, производство
Масштаб бизнесаЗаказы на 100+ млн ₽ в день, каталог из тысяч товаров
ГеографияРоссия, включая регионы с нестабильной связью
Особенности работыОфлайн-работа в полях, непрерывные интеграции прайс-листов, остатков и промо

Что происходило до начала проекта

  • В регионах с нестабильным интернетом синхронизация могла не уложиться в 15 минут и не завершиться вовсе.
  • Приложение забирало каталог мелкими порциями по 300 товаров из перегруженного сервиса: запросы падали по таймауту.
  • Фото товара весило около 1 МБ и загружалось заново при каждом открытии — было видно, как картинки прорисовываются.
  • В пиковые моменты методы чтения данных замедлялись с миллисекунд до 20 секунд.
  • При сбое связи или дата-центра заказы, собранные в полях, нельзя было передать дистрибьютору.
03
Цели и задачи

Каких результатов хотел достичь клиент

Цель проекта

Сделать так, чтобы торговый представитель и клиент не ждали систему, а заказы доходили до дистрибьютора при любом сбое.

01

Быстрая синхронизация

Обновлять данные в приложении за минуты даже при слабом интернете.

02

Отзывчивые каталоги

Открывать карточки и фото товаров без задержек на портале и в приложении.

03

Ровная работа в пики

Не тормозить пользователей во время массовой загрузки прайсов и остатков.

04

Ноль потерянных заказов

Сохранить продажи при падении связи, синхронизации или дата-центра.

04
Решение

Что разработала команда GROTEM

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

Непрерывность бизнеса · BCP

Аварийная выгрузка заказов

Если связь или основная система недоступны, представитель включает в приложении режим аварийной выгрузки:

  • приложение формирует файл с собранными заказами;
  • файл уходит дистрибьютору по почте или в мессенджере — в обход основной системы;
  • уникальный префикс в имени файла исключает дубли, когда синхронизация восстановится.
  • BCP
  • Офлайн
  • Защита от дублей
Мобильное приложение

Стабильная синхронизация каталога

Раньше приложение запрашивало товары напрямую у сервиса каталога, который одновременно принимал интеграции цен и промо. Теперь:

  • раз в 30 минут фоновая задача забирает полный каталог в собственную базу шлюза;
  • товары хранятся JSON-объектами — новые поля добавляются без миграций базы;
  • обновляются только изменённые товары — по ID и хешу;
  • порция данных выросла с 300 до 1 000 товаров.
  • Офлайн-first
  • Кеширование
  • Фоновые задачи
Каталоги и поиск

Лёгкие изображения и гибкий поиск

Картинки конвертируются в WebP и уменьшаются «на лету» при первом запросе — без переконвертации всего архива. Браузер и приложение кешируют их на год.

Поиск по каталогу перевели на Elasticsearch: он учитывает опечатки и окончания и ищет сразу по бренду, линейке, категории, упаковке, весу и названию.

  • WebP
  • Elasticsearch
  • Кеширование
База данных

Чтение из реплики и быстрая индексация промо

Интеграции без пауз переписывают тысячи прайс-листов и остатки, и запись тормозила чтение. Решения:

  • методы, помеченные в коде как только читающие, автоматически работают с репликой базы — чтение стало в 2 раза быстрее;
  • индексацию 7 000 товаров перевернули: вместо перебора «товар → все акции» система один раз строит словарь «акция → товары».
  • Read-реплика
  • Индексация
  • Кеш
05
Сложность

Особенности проекта

Оптимизировать пришлось живую систему: в ней постоянно работают сотни пользователей и непрерывные интеграции, а остановить продажи ради доработок нельзя.

01
Каждый сбой — потерянная выручка

В пределе сутки простоя означают потерю всех дневных заказов — около 100 млн ₽. Поэтому целевая метрика аварийного сценария — ноль потерянных заказов.

02
Формат, понятный каждому дистрибьютору

Аварийный файл должны принять учётные системы разных дистрибьюторов. Общие формулировки требований здесь не работают — к проработке формата нужно подключать самих дистрибьюторов.

03
Непрерывная запись

Интеграции работают круглосуточно, и в базе нет ни секунды без записи — из-за этого методы чтения вставали в очередь.

04
Перегруженный сервис каталога

Мобильное приложение ходило за товарами в тот же сервис, который принимает прайс-листы и промо, — его кеш постоянно сбрасывался.

05
Не только скорость, но и прозрачность

Пользователи не видели прогресса синхронизации и думали, что приложение зависло. Важно было показать, что процесс идёт.

06
Инженерная часть

Что было важно реализовать на уровне системы

Решения подбирали так, чтобы получить эффект без переписывания бизнес-логики и без переделки данных клиента.

Разделение экземпляров каталогаИндексация и выдача данных работают на разных экземплярах e-commerce платформы.
Прогресс и увеличенный таймаутПользователь видит статус синхронизации, а длинные операции успевают завершиться.
ImageProxy + NginxРесайз и конвертация в WebP «на лету» из S3 с кешированием на 1 год.
Реплика по атрибутуМетод переключается на read-only реплику одной пометкой ReadOnlyDB в коде.
Инвертированный индекс промоСловарь «акция → товары» строится один раз и отдаёт промо для любого товара из памяти.
Обновление платформыПереход каталога с .NET 6 на .NET 8 убрал зависимости при сборке и расширил логирование.
07
Результаты

Что получил бизнес

Синхронизация мобильного приложения стала быстрее в среднем в 5,2 раза: сеансы, которые раньше не укладывались в 15 минут, теперь могут пройти меньше чем за минуту.

5,2×

в среднем быстрее синхронизация мобильного приложения

10×

легче изображения товаров после перехода на WebP и ресайз

2×

быстрее методы чтения данных под нагрузкой

20 мин

на индексацию каталога с промо вместо 1 ч 20 мин

Процесс
До проекта
После запуска
Синхронизация в регионах
Обрывалась при слабой связи
В среднем в 5,2 раза быстрее
Максимальное время запроса каталога
До 32 секунд
Около 8 секунд
Фото товара
~1 МБ, без кеша
В 10 раз легче, кеш на год
Чтение под нагрузкой
До 20 секунд
В 2 раза быстрее, из реплики
Индексация промо
1 ч 20 мин
20 минут
Сбой связи или дата-центра
Заказы не доходят
Аварийная выгрузка файлом
  • Заметно пользователям — клиент подтвердил, что фото товаров в мобильном приложении больше не прорисовываются на глазах.
  • Защита выручки — у полевых продаж появился сценарий на случай сбоя: заказы доходят до дистрибьютора, даже когда основная система недоступна.
10
Стек

Технологии проекта

Бэкенд

.NET 8RabbitMQ

Каталог и поиск

Virto CommerceGraphQLElasticsearch

Изображения

ImageProxyNginxS3WebP

База данных

PostgreSQLRead-only реплика

Мобильное приложение

Flutter

Мониторинг

Grafana
Обсудим ваш проект

Поможем выбрать оптимальное решение для вашего бизнеса

Разберём задачу, предложим архитектуру решения и оценим сроки реализации — на первой консультации, бесплатно.

  • Покажем релевантный опыт на похожих проектах
  • Сформируем решение с учётом ваших задач и IT-ландшафта
  • Предложим следующие шаги без обязательств

Оставьте заявку на консультацию

Заполните обязательные поля — остальное обсудим в разговоре. Перезвоним или напишем в течение одного рабочего дня

Необходимо дать согласие на обработку персональных данных.
Бесплатно Ответ за 1 рабочий день Без обязательств

Спасибо! Данные отправлены.

Для подписки на рассылку подтвердите почту по ссылке в письме. Если письма нет, проверьте папки «Спам» и «Промоакции».