Клиент пришёл к нам с типичной ситуацией: онлайн-магазин на устаревшем шаред-хостинге, медленная отдача каталога, периодические таймауты в часы пик. Маркетинговые расходы шли впустую, потому что часть пользователей просто не дожидалась загрузки — люди уходили с открытой корзиной, а команда списывала это на «сезон» и «плохой трафик».
Мы разобрали проблему по шагам: сначала измерили, потом нашли узкие места, потом перенесли инфраструктуру и только после этого начали оптимизировать код. В этом кейсе — весь путь с цифрами, конфигурациями и ошибками, которых удалось избежать.
Исходная ситуация
На момент обращения у магазина было около 8 000 SKU и 3 000 — 5 000 уникальных посетителей в сутки. Пиковая нагрузка приходилась на вечерние часы и распродажи: с 19:00 до 23:00 приходило до 60% суточного трафика, а во время акций количество одновременных сессий вырастало втрое.
Магазин работал на виртуальном хостинге, который выбрали ещё на старте, когда в каталоге было 300 товаров. Тарифа хватало ровно до момента, пока ассортимент не вырос в двадцать раз: база данных и веб-сервер жили на одной машине и делили общий пул ресурсов с соседними аккаунтами.
Что мы увидели в метриках
- Время ответа сервера в пике доходило до 4,8 секунды при норме до 0,8 секунды.
- Каждый десятый запрос к каталогу завершался таймаутом — пользователь видел белый экран.
- Веб-сервер и база данных конкурировали за один и тот же пул ресурсов и вытесняли друг друга.
- Кеш сбрасывался при каждом обновлении цен, а прайс приходил из 1С четыре раза в день.
Обратите внимание: снимите контрольные метрики до переезда. Без них не получится показать эффект от миграции ни команде, ни бизнесу — а через месяц никто уже не помнит, каким сайт был раньше.
Что именно тормозило
Первая гипотеза была очевидной: «не хватает ресурсов, нужен сервер побольше». Мы её проверили и частично подтвердили, но дело было не только в железе. Медленнее всего отдавались страницы каталога с фильтрами: каждый переход по фильтру собирал полную выборку товаров с ценами, остатками и характеристиками, без кеша и без ограничения по выборке.
Проблему усиливал импорт из 1С. Во время выгрузки прайса база данных уходила в блокировки на 30 — 90 секунд, и в это время сайт для покупателей практически останавливался. Импорт запускался по расписанию, в том числе в 20:00 — ровно в вечерний пик.
Профиль запросов до переезда
Мы собрали медленные запросы за сутки и сгруппировали их по типу страницы. Самый тяжёлый запрос — выборка товаров категории с фильтрами по характеристикам через JOIN по четырём таблицам.
| Тип страницы | Доля запросов | Среднее время ответа |
|---|---|---|
| Каталог с фильтрами | 41% | 3,9 с |
| Карточка товара | 28% | 1,4 с |
| Поиск по каталогу | 17% | 2,6 с |
| Корзина и оформление | 14% | 0,9 с |
Проверить это на своём проекте можно без сложных инструментов — достаточно двух команд:
# сколько реально отдаётся страница каталога
curl -o /dev/null -s -w "TTFB %{time_starttransfer} / total %{time_total}\n" https://example.com/catalog/
# десять самых долгих запросов за сутки
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
Осторожно: не включайте лог медленных запросов на продакшене без ограничения по размеру файла. На нагруженном проекте он способен занять десятки гигабайт за сутки и положить сервер уже по свободному месту на диске.
План миграции
Мы договорились с клиентом о главном условии: переезд без простоя и без «ночи переключения» на выходных. Это значит, что новая инфраструктура должна была работать параллельно со старой, а трафик переключался только после того, как мы убедимся в её стабильности.
- Развернули копию магазина на VDS и подняли отдельный сервер базы данных. Данные синхронизировали репликацией, чтобы не терять заказы, оформленные на старой площадке.
- Перенесли статику и медиа в объектное хранилище и подключили CDN. Веб-сервер перестал отдавать 40 гигабайт картинок и разгрузился ещё до переключения трафика.
- Настроили кеширование каталога с точечной инвалидацией: при обновлении цен сбрасываются только затронутые категории, а не весь кеш целиком.
- Перенесли импорт из 1С на ночное окно и добавили ограничение на размер транзакции, чтобы выгрузка больше не блокировала базу на минуты.
- Прогрели кеш на новой площадке краулером по карте сайта и только после этого переключили DNS, снизив TTL заранее до 300 секунд.
Совет: снижайте TTL записей DNS за сутки до переключения. Тогда трафик перейдёт на новую площадку за минуты, а не за двое суток, и вам не придётся поддерживать два работающих магазина неделю.
Как выбирали конфигурацию
Считали от пиковой нагрузки, а не от средней: если сервер справляется только со средними значениями, каждая распродажа превращается в аварию. За основу взяли данные мониторинга за три месяца и добавили запас на рост ассортимента.
| Параметр | Было: шаред-хостинг | Стало: VDS и отдельная БД |
|---|---|---|
| Процессор | Общий пул без гарантий | 4 выделенных ядра |
| Память | 1 ГБ с лимитом на процесс | 8 ГБ |
| Диск | SATA, общий канал | NVMe, 120 ГБ |
| База данных | На том же сервере | Отдельный инстанс |
| Медиа | В файловой системе сайта | Объектное хранилище и CDN |
Термины, которые встречаются в кейсе
- TTFB
- Время до первого байта: сколько браузер ждёт первый ответ сервера. Показывает, насколько быстро работает бэкенд, и не зависит от вёрстки и картинок.
- Точечная инвалидация кеша
- Сброс не всего кеша, а только тех страниц, данные которых изменились. Позволяет обновлять цены без просадки производительности.
- Прогрев кеша
- Обход страниц роботом до того, как на них придут пользователи. Первый посетитель получает уже готовую страницу, а не собирает её заново.
- Предсказуемая скорость в пике и на распродажах.
- Импорт из 1С больше не влияет на покупателей.
- Медиа отдаются из CDN, ближе к пользователю.
- Стоимость инфраструктуры выросла на 2 400 ₽ в месяц.
- Появилась зона ответственности за обновления сервера.
- Двухнедельная параллельная работа двух площадок.
Результат
Время первого экрана упало с 4,8 до 1,6 секунды, отказы по таймаутам исчезли, конверсия выросла на 12% к контрольному периоду. Отдельно отметим стабильность: за первую распродажу после переезда сайт не ушёл в ошибки ни разу, хотя трафик был выше прошлогоднего на четверть.
| Метрика | До переезда | После переезда |
|---|---|---|
| Время первого экрана | 4,8 с | 1,6 с |
| Таймауты в пике | до 10% запросов | 0% |
| Простой во время импорта | 30 — 90 с четыре раза в день | нет |
| Конверсия | 1,7% | 1,9% |
Мы готовились к сложному переезду с простоем на все выходные, а магазин не остановился ни на минуту. Первые же выходные после миграции дали рекорд по заказам — при том же бюджете на рекламу.
Игорь Величко технический директор магазина
Хорошая практика: держите старую площадку включённой ещё неделю после переключения DNS. Это стоит немного, зато даёт возможность спокойно вернуть трафик, если на новой инфраструктуре вылезет что-то неожиданное.
Выводы
Перенос инфраструктуры окупился за два месяца. Главный вывод не про железо: сначала измеряем, потом переносим, и только затем оптимизируем код. Если бы мы начали с оптимизации запросов на старом хостинге, получили бы выигрыш в десятые доли секунды и потратили в разы больше времени.
Сейчас клиент готовится к запуску мобильного приложения и расширению ассортимента до 20 000 SKU. Следующий шаг — вынести поиск в отдельный сервис и добавить второй веб-сервер за балансировщиком. Другие истории клиентов собраны в разделе кейсов.