Что отключить на время пика, чтобы устояла корзина
За неделю до крупной распродажи все разговоры в команде интернет-магазина вертятся вокруг одного вопроса: выдержит ли сервер. Обычно на него отвечают докупкой мощности — берут VPS побольше, добавляют реплику, кешируют что могут. Но есть более дешёвый и часто более надёжный рычаг, о котором вспоминают уже во время пожара: не всё, что работает на сайте в обычный день, обязано работать в момент пика. Часть функциональности можно осознанно выключить на несколько часов — и именно это, а не лишнее железо, чаще всего спасает конверсию, когда трафик прыгает в три-пять раз.
Содержание
- Почему нельзя просто «докинуть мощности»
- Критическое ядро: что нельзя отключать ни при каких обстоятельствах
- Что можно выключить: три категории кандидатов
- Как физически отключать: feature flag, а не правка кода
- Осторожно с кешированием того, что выключаете
- Что оставить работающим наполовину, а не выключать целиком
- Порядок действий: чек-лист подготовки к пику
Почему нельзя просто «докинуть мощности»
Идея «на пик просто возьмём сервер помощнее» подкупает простотой, но у неё есть два практических ограничения. Первое — по деньгам: держать инфраструктуру, рассчитанную на пиковую нагрузку, впустую 363 дня в году накладно, особенно если пик случается раз-два в году, как в случае с сезонными распродажами. Экономику такого расчёта — сколько на самом деле стоит час простоя именно в пиковый момент, а не в среднем по году — подробно разбирали в статье про цену простоя на пике распродажи и сезонный множитель: усреднённая цифра занижает реальный ущерб в разы, и именно поэтому чистое масштабирование «про запас» редко экономически оправдано.
Второе ограничение серьёзнее: мощность процессора и RAM не спасает, если узкое место не в них. Реальный интернет-магазин на пике почти никогда не упирается в CPU фронтенда — он упирается в конкретные дорогие операции: пересчёт «с этим товаром часто покупают» для каждого товара на лету, обращение к внешнему API за точным остатком на каждой карточке, построение персонализированной ленты рекомендаций под залогиненного пользователя. Эти операции масштабируются с числом посетителей хуже линейного, и добавление ядер лишь отодвигает момент коллапса на несколько минут, а не убирает его.
Здесь работает вторая стратегия: вместо того чтобы удерживать всю функциональность на увеличенной мощности, временно урезать саму функциональность до критического ядра — так же, как приёмный покой при перегрузке не пытается обслужить всех одинаково хорошо, а сортирует, что должно работать всегда, а что можно отложить.
Критическое ядро: что нельзя отключать ни при каких обстоятельствах
Прежде чем говорить, что выключать, нужно чётко зафиксировать, что выключать нельзя. Это ядро — четыре шага воронки, которые напрямую конвертируются в деньги:
- Просмотр карточки товара. Пользователь должен увидеть название, цену, фото, кнопку «в корзину». Без этого продажи не будет физически.
- Добавление в корзину. Технически простая, но критичная операция — если она подвисает или падает под нагрузкой, пользователь уходит немедленно, даже не начав оформление.
- Оформление заказа (чекаут). Ввод адреса доставки, выбор способа получения, подтверждение состава заказа.
- Оплата. Переход на платёжный шлюз и обработка колбэка о результате оплаты.
Всё остальное на сайте существует для того, чтобы усилить конверсию в этих четырёх шагах или увеличить средний чек — но не является необходимым условием самой продажи. Именно эта разница и даёт пространство для манёвра: вы не выключаете магазин наполовину, вы отсекаете вспомогательное вокруг работающего core flow.
Отдельно стоит подчеркнуть: платёжный путь — самое чувствительное место во всей системе, и его цена ошибки видна не только на пике. Известны случаи, когда «безобидное» изменение конфигурации (например, отключение устаревшего протокола шифрования) случайно задевало именно платёжный шлюз, потому что его не тестировали изолированно от остальных правок. Правило простое: критическое ядро на пике не трогают вообще, ни ради экономии ресурсов, ни ради технического обслуживания.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверЧто можно выключить: три категории кандидатов
Дальше — конкретные кандидаты на отключение, отсортированные по тому, насколько безболезненно их можно убрать на несколько часов.
1. Рекомендательные блоки
«С этим товаром часто покупают», «вам может понравиться», «похожие товары» — как правило, самая тяжёлая для бэкенда часть карточки товара, потому что подбор требует либо запроса к сервису персонализации, либо агрегирующего запроса к БД с джойнами по истории заказов. При этом блок отвечает за прирост конверсии на проценты, а не за саму возможность купить — его отсутствие не остановит ни одной покупки.
Механику того, как вообще устроены такие блоки и почему они бывают тяжёлыми (в том числе при интеграции с внешними SaaS-сервисами персонализации), разбирали в статье про рекомендации книжного магазина без выгрузки базы покупателей наружу — там речь больше про приватность данных, но архитектурно это тот же тяжёлый блок, который на пике логично временно погасить или подменить статичным, заранее закешированным списком бестселлеров.
Практический вариант отключения — не «убрать совсем», а откатиться на дешёвую статическую замену: топ-10 самых продаваемых позиций категории, посчитанный заранее (например, ночным cron-джобом) и отданный как обычный кешируемый JSON или встроенный в HTML-шаблон. Пользователь по-прежнему видит блок с товарами, но сервер больше не считает персональную выборку на каждый запрос.
# было: персональный запрос на каждый рендер карточки
SELECT product_id, score FROM recommendations
WHERE user_id = :uid AND base_product_id = :pid
ORDER BY score DESC LIMIT 6;
# на пике: статичный топ по категории, обновляется раз в сутки
GET /cache/top_products/category_42.json
2. Точные остатки в реальном времени
Показ остатка «в наличии: 3 шт.» с точностью до штуки обычно требует либо прямого запроса к таблице остатков на каждый рендер карточки, либо похода в учётную систему склада. Под нагрузкой это одна из первых точек, где база начинает захлёбываться блокировками — множество параллельных запросов читают и потенциально резервируют один и тот же счётчик.
На пике разумно ослабить точность вместо отказа от показа остатка вообще:
- Заменить точное число на грубые статусы: «в наличии», «осталось мало», «под заказ» — с обновлением раз в 5-15 минут вместо реального времени.
- Считать остаток из кеша (Redis, локальная память приложения), а не из БД напрямую, принимая, что цифра может на короткое время разойтись с реальностью на 1-2 позиции.
- Резервирование товара при оформлении заказа оставить точным и синхронным — расхождение в отображаемом остатке допустимо, а продажа того, чего уже нет, недопустима. Это разные операции: одна информационная (что видит пользователь), другая транзакционная (что бронируется в момент заказа), и ослаблять точность стоит только в первой.
Логика ослабления консистентности здесь та же, что применяется и в других сценариях с распределёнными остатками: не любая задержка в отображении остатка критична, критична задержка именно в проверке остатка на этапе фактической продажи.
3. Сложная персонализация и второстепенная аналитика
Сюда попадает всё, что подстраивает витрину под конкретного пользователя за пределами базовых рекомендаций: динамическое ценообразование под сегмент, A/B-тесты с расчётом когорты на лету, персонализированные баннеры, геотаргетированный контент через внешний API геолокации. Каждый такой слой — дополнительный запрос или ветвление логики на пути каждого пользователя, при этом ни один не влияет на способность купить товар.
Отдельная категория — фоновая аналитика и трекинг, синхронно блокирующие ответ пользователю: отправка события в стороннюю систему аналитики до рендера страницы, синхронная запись в лог, вызов вебхука в CRM при каждом просмотре карточки. Всё это должно быть асинхронным в норме, но если на пике где-то обнаруживается блокирующая синхронная интеграция — её лучше временно отключить, а не пытаться разогнать.
Как физически отключать: feature flag, а не правка кода
Самая частая ошибка — решать, что отключать, в момент, когда пик уже начался, и лезть за это время в код. Правки под нагрузкой, тем более экстренные, сами по себе источник риска: спонтанное отключение без подготовленного пути обратно почти всегда откликается позже — либо забытым выключенным блоком, либо новой ошибкой, внесённой в спешке.
Правильный порядок — подготовить переключатели заранее, до пика, и на самом пике только дёргать готовый рубильник:
- Feature-флаги в конфиге приложения, а не в коде. Простейший вариант — булевы значения в environment-переменных или в конфигурационном файле, которые читаются при старте приложения или, ещё лучше, на лету без рестарта (через Redis-ключ, consul, etcd или просто файл, который приложение перечитывает раз в несколько секунд).
# config/features.yml
recommendations_enabled: true
realtime_stock_enabled: true
personalization_enabled: true
# при пике — правится один файл или ключ в Redis,
# приложение подхватывает изменение без деплоя
SET feature:recommendations_enabled false
SET feature:realtime_stock_enabled false
- Явный fallback для каждого флага. Флаг «выключить рекомендации» должен вести не в пустоту, а в заранее реализованную статичную ветку (топ товаров из кеша). Реализовывать fallback на ходу, во время инцидента — то же самое, что писать код под нагрузкой, только хуже, потому что решение принимается в панике.
- Проверка на staging заранее. Флаги нужно один раз реально прогнать на копии продакшена — включить, выключить, посмотреть, что страница не разваливается вёрсткой и не кидает 500-ю ошибку там, где раньше был блок рекомендаций. Методика степ-нагрузочного теста, которая помогает понять, при каком RPS конкретно рекомендательный блок начинает контрибьютить в деградацию сильнее остальных частей страницы, разобрана в статье про порог отказа под нагрузкой и как его найти тестом, не положив продакшен.
- Runbook с чек-листом, а не память дежурного. Простой markdown-файл или страница в вики с перечнем: какие флаги существуют, что каждый из них выключает, какой командой дёрнуть, кто принимает решение о включении обратно. На пике решения принимаются быстро, и документ должен быть написан так, чтобы дежурный, который видит его впервые в 2 часа ночи, за минуту понял, что делать.
Осторожно с кешированием того, что выключаете
Отдельная ловушка возникает, когда отключаемый блок заменяют не статикой, а обычным HTTP-кешем на уровне прокси — и кешируют персонализированный ответ целиком, как будто он одинаков для всех. Реальный инцидент именно такого рода разбирали в статье про кеш, который отдавал чужие корзины из-за отсутствия идентификатора пользователя в ключе кеша: попытка снять нагрузку кешированием GET-эндпоинта, отдающего персональные данные, обернулась утечкой чужих корзин между пользователями.
Вывод из этого кейса напрямую применим к теме отключения функциональности: если вы гасите персонализированный блок ради нагрузки, не пытайтесь на скорую руку «закешировать как есть» — либо отключайте целиком с явным статичным fallback, либо кешируйте только то, что действительно одинаково для всех пользователей (общий топ товаров, а не персональная лента). Ключ кеша обязан включать всё, от чего реально зависит содержимое ответа, а самый надёжный способ не ошибиться в этом под давлением пика — вообще не кешировать персонализированные ответы, а подменять их заранее подготовленной статикой.
Что оставить работающим наполовину, а не выключать целиком
Не всё сводится к бинарному вкл/выкл. Часть функциональности можно не отключать, а деградировать частично — это часто лучше, чем полное отключение, потому что пользователь меньше замечает разницу:
| Функциональность | Полное отключение | Частичная деградация (обычно лучше) |
|---|---|---|
| Остаток товара | Скрыть цифру совсем | Показывать грубый статус вместо точного числа |
| Поиск по каталогу | Отключить поиск | Упростить до точного совпадения, убрать «умную» релевантность и опечатко-устойчивость |
| Фильтры в каталоге | Убрать все фильтры | Оставить популярные (цена, категория), убрать редкие фасеты с дорогими агрегациями |
| История заказов в личном кабинете | Скрыть раздел | Показывать последние 5 заказов из кеша вместо полной постраничной выборки из БД |
| Изображения товара | Не грузить вовсе | Отдавать уменьшенную версию через CDN вместо оригинала в высоком разрешении |
Общий принцип таблицы: там, где это возможно, лучше упростить операцию, чем убрать её — так пользователь ощущает не «магазин частично сломан», а «магазин чуть менее умный, чем обычно», что почти не влияет на решение о покупке.
Порядок действий: чек-лист подготовки к пику
Собрать всё выше в последовательность, применимую за 2-4 недели до известного пика (распродажа, сезонный всплеск, рекламная кампания):
- Составить список некритичной функциональности сайта — пройтись по core flow (карточка, корзина, чекаут, оплата) и выписать, что на нём есть сверх обязательного минимума.
- Для каждого пункта определить: полное отключение или частичная деградация, и подготовить конкретный fallback (статичный список, кешированное значение, упрощённая версия).
- Реализовать переключение через конфигурационный флаг, а не через комментирование кода или деплой отдельной ветки.
- Прогнать на staging-копии сценарий «флаг выключен» — убедиться, что вёрстка не разваливается и ошибок в логах не прибавляется.
- Провести степ-нагрузочный тест с включёнными и выключенными флагами, зафиксировать разницу в пороге отказа.
- Написать runbook: кто, когда и какой командой включает режим деградации, и какой сигнал (latency, error rate, load average) служит триггером.
- После пика вернуть всё обратно и закрыть инцидент-чеклист — забытый выключенный флаг «до следующего раза» частая причина того, что персонализация тихо не работает месяцами.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Чем это отличается от статьи про graceful degradation в целом?
Общий принцип graceful degradation — деградировать по частям вместо полного отказа — применим к любой системе, от API до систем реального времени. Эта статья — частный случай именно для интернет-магазина: конкретно про то, какие блоки на витрине можно отключить (рекомендации, точный остаток, персонализация) и какие четыре шага воронки (карточка, корзина, чекаут, оплата) отключать нельзя ни при каких обстоятельствах.
Стоит ли отключать функциональность на пике, если сервер и так справляется по CPU и RAM?
Если метрики (latency, error rate, load average) остаются в норме — отключать ничего не нужно, преждевременная деградация только ухудшит опыт без необходимости. Флаги готовятся заранее именно на случай, если метрики начнут ухудшаться, а не включаются профилактически по календарю.
Как понять заранее, какой блок «тяжелее» остальных?
Через степ-нагрузочный тест на staging-копии с профилированием: постепенно наращивать нагрузку и смотреть, какой конкретно запрос или блок первым начинает давать рост латентности или ошибок. Методика такого теста и типичные ошибки при его проведении разобраны в статье про поиск порога отказа, упомянутой выше.
Можно ли автоматизировать отключение вместо ручного флага?
Да, продвинутый вариант — автоматическое включение деградации по порогу метрики (например, если p95 latency чекаута превышает заданное значение 5 минут подряд, система сама переключает флаг рекомендаций). Это надёжнее ручного дежурного, но требует, чтобы автоматика была протестирована так же тщательно, как и ручной путь — ложное срабатывание среди ночи без трафика ничем не лучше пропущенного реального пика.
Что делать, если пик оказался неожиданным и флагов заранее не было?
В моменте — резать самое дорогое по запросам к БД первым (обычно это персонализированные выборки), даже грубым способом вроде временного возврата статичной страницы через правку конфига веб-сервера. После инцидента — довести до подготовленных флагов, чтобы в следующий раз не решать это вручную под давлением.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →