Установка Vendure: что ломается на боевом контуре магазина
Боевой контур магазина рвётся не на старте, а на пиковой нагрузке. Когда распродажа совпадает с рассылкой по базе покупателей, каталог собирает каждый листинг фильтров из десятков обращений к базе, пул соединений перестаёт успевать, и время ответа растёт нелинейно: часть корзин теряет выбранные позиции, покупатель уходит на страницу ошибки. То же узкое место каталога всплывает при пересчёте скидок и остатков — тяжёлая задача выполняется в том же процессе, что и отдача страницы.
Второй разрыв — зависшие оплаты. Шлюз списал средства, подтверждение не дошло или обработалось дважды, заказ остался в промежуточном статусе: товар не зарезервирован, возврат делается вручную, а сверка с провайдером идёт по выгрузкам раз в сутки, когда расхождений уже накопилось на несколько дней.
Третий — ручные правки при обновлении. Модули, схема данных и оформление заказа правятся прямо на боевом сервере, потому что так быстрее; после следующего релиза изменения затираются или расходятся с репозиторием, и обновление превращается в ночную операцию с ручным откатом и прогоном сценариев по бумажному чек-листу.
Установка Vendure на отдельный контур снимает все три узла. Каталог отдаётся из прогретого кеша, тяжёлые задачи — индексация, пересчёт цен, письма — уходят в отдельные воркеры через очередь, подтверждения оплат обрабатываются идемпотентно, с повторами и журналом расхождений, чтобы повтор вебхука не создавал второй заказ. Правки при этом живут в репозитории: миграции версионируются, настройки окружения вынесены из кода, а сборка и схема проверяются до выката.
Разбираем, как это закрывается: от подготовки сервера и ролей до очередей, кеша и проверок перед публикацией.
Что даёт грамотная сборка магазина: скорость и отказоустойчивость
Сборка интернет-магазина на Vendure — один предсказуемый контур: каталог, корзина, оформление заказа и админка работают на общем наборе моделей и контрактов. Поэтому время отклика каталога не растёт вместе с размером выборки: фильтры и постраничный вывод считает база, а тяжёлые агрегаты отдаются из прогретого кэша. Список из сотен позиций открывается так же быстро, как карточка одного товара.
Отказоустойчивость здесь — набор решений, а не обещание: несколько экземпляров приложения за балансировщиком, вынесенные фоновые обработчики для писем, выгрузок и синхронизации остатков, раздельные пулы подключений к базе для витрины и админки. При выпадении узла трафик уходит на живой экземпляр, а время восстановления измеряется минутами, а не часами простоя.
Вместе с этим уходит целый класс отказов, который обычно всплывает в пик: рассинхрон остатков между витриной и складом, двойное оформление одного заказа при повторной отправке формы, потерянные позиции в корзине после перезапуска. Это закрыто транзакциями на уровне базы и повторяемыми операциями оформления — статус заказа не зависит от того, успел ли ответить внешний сервис.
Устойчивость к нагрузке проверяется не синтетикой, а распродажей: мы ограничиваем число параллельных тяжёлых запросов, кэшируем каталог и категории, а оформление заказа держим на отдельном пуле. Витрина под нагрузкой не тормозит оплату, поэтому доля заказов, доведённых до оплаты без повторов и ошибок, остаётся ровной и в пиковые часы.
Варианты развёртывания: свой сервер, аренда, смешанная схема
Размещение магазина на Vendure определяет не размер каталога, а то, кто отвечает за обновления ядра, резервное копирование и масштабирование в пиковые часы. Приложение требует процесс-менеджера, базы данных, обработчика фоновых задач и хранилища медиа — это можно собрать самостоятельно, отдать провайдеру или разделить контуры. Ниже — три рабочих схемы и их ограничения.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Свой сервер | Нужен полный контроль над окружением, свои правила доступа и размещение в конкретной юрисдикции | Патчи ОС, обновления приложения и резервные копии — на вашей стороне; ошибка в конфигурации даёт простой без внешней поддержки |
| Аренда управляемого сервера | Нет выделенного инженера, нужен быстрый запуск и предсказуемая базовая эксплуатация | Ниже потолок по нагрузке, ограничения на длительные фоновые задачи и размер очереди, окна обслуживания задаёт провайдер |
| Смешанная схема | Витрину и админку обслуживает провайдер, а тяжёлые задачи — обработка медиа, выгрузки, обмен с учётной системой — выносятся на отдельный контур | Сложнее сеть и права доступа; обязательны единые правила сборки и одинаковые переменные окружения на всех контурах |
Схему фиксируют до переноса данных, а не после: от неё зависят способ деплоя, точки резервного копирования и порядок откатов. На этапе оценки мы сверяем выбранный вариант с профилем нагрузки и проверяем, что фоновые задачи и база не окажутся узким местом при росте каталога.
Установка Vendure по шагам: от аудита до передачи
Порядок работ выстроен так, чтобы каждое решение опиралось на факты предыдущего шага. Сначала фиксируем, что уже работает в контуре, затем проектируем схему — и только потом трогаем боевую среду, чтобы установка не превратилась в серию аварийных правок.
- Аудит контура. Разбираем серверы, базу, кэш, очереди, DNS и сертификаты, текущие лимиты и точки отказа. На выходе — карта того, что переиспользуем, а что меняем.
- Схема развёртывания. Определяем, где живут приложение, база, медиа и фоновые задачи, как между ними ходят запросы и где теряется сессия. Схему согласуем до первой команды на сервере.
- Права доступа. Отдельный системный пользователь, разложенные по каталогам секреты и переменные окружения, роли базы по минимуму необходимого: приложение не работает от суперпользователя.
- Установка и настройка. Разворачиваем актуальную ветку Vendure, прогоняем миграции, подключаем плагины и обработчики очередей, настраиваем кэш и индексацию каталога.
- Проверка под нагрузкой. Прогоняем сценарии покупателя — поиск, корзина, оформление заказа — на профиле, близком к реальному трафику, и смотрим время ответа и поведение базы под пиком.
- Копии и откат. Настраиваем регулярные снимки базы и медиа и проверяем восстановление на отдельном стенде, а не только факт создания копии.
- Передача проекта. Отдаём документацию, регламент обновлений, разбор схемы и доступы вашей команде.
На выходе — работающий контур и понятный набор действий на случай обновления или сбоя.
Что остаётся у вас: конфигурации, схемы, регламенты, доступы
Мы сдаём не только работающий сервер, но и всю обвязку вокруг него: конфигурации развёртывания, схемы инфраструктуры, регламенты и доступы. Комплект собирается так, чтобы его приняла любая другая команда — без наших устных пояснений и без восстановления решений по памяти.
- Конфигурации развёртывания — файлы окружения, параметры сборки и запуска приложения, настройки каталога, корзины и оформления заказа с пояснением, какое значение на что влияет.
- Схемы инфраструктуры — что и где размещено: сервер приложения, база данных, кэш, очереди, внешние сервисы, как они связаны между собой и где находятся точки отказа.
- Регламент обновлений — порядок выпуска новой версии, процедура отката на предыдущую, список проверок до и после выкладки.
- Резервное копирование — расписание, глубина хранения копий, регламент проверки восстановления и сама процедура разворота из копии на чистом окружении.
- Доступы и роли — перечень учётных записей, уровни прав, место хранения секретов и порядок их плановой смены.
- Документация — карта кода и плагинов, описание нестандартных решений, журнал изменений и известных ограничений с указанием, что и почему сделано именно так.
- Инструкция для дежурной команды — как читать журналы, какие показатели считать нормой и при каких признаках поднимать тревогу.
Отдельным блоком идёт документация по доработкам: что именно мы расширяли в Vendure, где лежит код плагинов, как их обновлять вместе с ядром и что сломается, если пропустить промежуточную версию. Такой комплект можно передать стороннему подрядчику или собрать свою команду — работа продолжится с той же точки, а не с повторного изучения системы.
Кейс: магазин перестал терять заказы при пиковых нагрузках
До переноса магазин с каталогом на 12 000 позиций не держал пик: в дни распродаж до 4% заказов терялось. Оплата покупателя проходила, а запись заказа не создавалась — разбор ложился на поддержку. Обновления выкладывали ночью, останавливая приём заказов на 40 минут.
Что изменили
Каталог перенесли со сверкой: выгрузили через программный интерфейс старой платформы, сверили число позиций, остатки и привязку к категориям, сквозные идентификаторы сохранили — адреса страниц и позиции в поиске не поехали. Магазин развернули на актуальной ветке Vendure в конфигурации с несколькими узлами приложения.
Заказ и списание остатка пишутся одной транзакцией, у попытки есть ключ идемпотентности: повторная отправка не создаёт дубль, а сбой откатывает заказ целиком. Корзину и сессии вынесли в общее хранилище — перезапуск процесса больше не сбрасывает покупателя посреди оформления. Выкладка идёт поочерёдно на резервные узлы, трафик возвращается после проверки готовности, поэтому обновление перестало быть окном простоя.
Что стало
| Метрика | До | После |
|---|---|---|
| Потерянные заказы на пике | до 4% | 0 |
| Простой при обновлении | 40 минут | без остановки |
| Отклик страницы категории | 1,8 с | 0,4 с |
| Заказы, доходящие до подтверждения | 96% | 99,8% |
На сопоставимой распродажной нагрузке не потеряно ни одного заказа, поддержка перестала разбирать жалобы «оплатил, но не пришло». Дальше разбираем, как такая конфигурация собирается с нуля.
Что делать, если магазин уже работает на другой платформе?
Переносим действующий магазин в два контура: прежний продолжает принимать заказы, пока новый на Vendure и NestJS наполняется каталогом и прогоняется в тестовом режиме. Продажи не останавливаются ни на этапе импорта, ни на этапе сверки — простой сводится к короткому окну записи в момент переключения.
Каталог импортируем из выгрузки старой платформы: сопоставляем артикулы, варианты, атрибуты, категории, медиа и переводы по ключам, а не по названиям. Импорт идемпотентный — повторный прогон обновляет записи, а не создаёт вторую карточку на тот же товар, поэтому расхождения можно устранять итеративно, не ломая уже перенесённое.
Историю заказов и клиентов переносим отдельным проходом и держим только для чтения: статусы, суммы, позиции и привязки к покупателям. Так отчётность, повторные покупки и возвраты по старым заказам остаются рабочими, но не пересекаются с новым учётом.
Пока идёт перенос, остатки и цены тянутся из прежней платформы дельтами по времени изменения — новый контур видит актуальную картину, но продажи закрывает старый магазин. Переключение делаем на низком трафике: короткое окно записи, финальная дельта, перевод трафика и сверка заказов по счётчикам. Прежний контур остаётся горячим резервом и каналом отката, пока расхождения не уйдут в ноль.
Отдельно выносим в реестр то, что не переносится автоматически: сертификаты, промокоды и бонусные балансы. Их миграцию согласуем до переключения — иначе после запуска всплывут расхождения в скидках, которые придётся разбирать вручную на живых заказах.
Частые сомнения перед стартом: нагрузка, доступы, обновления
Сомнения перед стартом обычно одни и те же: встроится ли платформа в текущий стек, выдержит ли каталог пиковую нагрузку, кто и что меняет в админке, как проходят обновления и что останется после сбоя.
Встроится ли платформа в наш текущий стек?
Vendure — приложение на NestJS, расширения пишутся как обычные модули этого фреймворка. Разработчики остаются в привычных слоях и схеме миграций вместо изучения отдельного языка плагинов. Внешние системы подключаем через штатный API платформы.
Выдержит ли каталог пиковую нагрузку?
Каталог на чтение отдаётся через кэш, поэтому выдача категорий и карточек не упирается в базу на каждом запросе. Фильтры, подборки и поиск уходят на отдельный сервис. Перед запуском прогоняем нагрузочный тест на пиковом профиле и смотрим время ответа каталога и корзины при всплеске трафика.
Как разграничиваются права доступа?
Роли описываем по операциям: контент-менеджер правит карточки и медиа, товаровед — цены и остатки, поддержка видит заказы, но не меняет каталог. Вход в админку — через корпоративную авторизацию, изменения попадают в журнал: видно, кто и когда снял товар с публикации.
В каком порядке выходят обновления?
Плановые обновления ставим в согласованное окно: сначала копия боевой базы, прогон миграций и проверок на ней, потом выкладка. Мажорные переходы делаем отдельным этапом с проверкой расширений. Откат возвращает предыдущую сборку и схему базы, поэтому окно не растягивается на ночь.
Что с резервными копиями?
Ежедневный дамп базы и снапшот медиа храним вне основного контура, отдельно от продакшена. Раз в квартал разворачиваем копию на тестовом стенде: копия, которую ни разу не восстанавливали, копией не считается. Поэтому возврат в рабочее состояние измеряется минутами.
Обсудим задачу: с чего начнём и что нужно с вашей стороны
Разговор начинаем с разбора задачи: что уже работает, где узкие места и какой результат нужен на выходе. Нам важно понять не только «нужен интернет-магазин», а как устроен ваш каталог, кто и как с ним работает ежедневно, какие процессы ломаются сейчас. По итогам возвращаемся с оценкой и планом — с этапами, порядком выкладки и точками, где потребуется ваше решение.
Чтобы оценка была предметной, а не «на глазок», от заказчика нужен минимум:
- доступ к репозиторию либо архив с текущим кодом и настройками окружений;
- описание инфраструктуры: где разворачиваем, есть ли ограничения по сети, доступам и резервному копированию;
- перечень интеграций — приём платежей, доставка, склад, учётная система, рассылки;
- структура каталога: категории, варианты товаров, языки и валюты, правила скидок и акций;
- ожидаемая нагрузка: сколько позиций в каталоге и какой пик заказов в сутки;
- ответственный с вашей стороны — кто принимает работу и согласует спорные места.
Этого хватает, чтобы собрать план: подготовка окружения, установка Vendure на NestJS, перенос данных, подключение интеграций, проверка под нагрузкой и запуск. Сроки называем по этапам, а не одной цифрой — так видно, что от чего зависит и где мы ждём ваших данных. Опишите задачу — вернёмся с оценкой, планом и вопросами, которые стоит закрыть до старта.







