dmilyin.ru AI-разработка · Нижний Новгород · обновлено 2026-07-09


Кейсы Клиентский проект

Интернет-магазин на CS-Cart (58 000 товаров): TTFB 16 → 1 секунда без апгрейда сервера

Магазин сантехники на CS-Cart (~58k товаров) грузился 12–16 с. Причина — не сервер, а забытый флаг разработки, отключивший кеш. Диагностика вернула TTFB к ~1 с без апгрейда.

Обложка кейса: Интернет-магазин на CS-Cart (58 000 товаров): TTFB 16 → 1 секунда без апгрейда сервера

Задача

Интернет-магазин сантехники на CS-Cart, каталог ~58 000 товаров. Страницы категорий открывались 5–16 секунд, главная — 2.7 секунды, поиск — 9–11 секунд. Перед запуском рекламы такой сайт сливает бюджет: посетитель уходит до того, как увидит товар. Владелец считал, что упирается в слабый сервер, и думал про апгрейд тарифа.

Это типичная ситуация для магазина с большим каталогом на «коробочной» CMS: тормоза лечат деньгами за железо, хотя причина чаще в конфигурации и кеше. Я начал не с покупки ресурсов, а с диагностики — где именно теряются секунды.

Решение

Сначала замеры и поиск корня, потом изменения. На сервере хватало ресурсов (8 ядер, ~11 ГиБ RAM) — значит, дело не в мощности, а в том, что каждый запрос делал лишнюю работу.

Корневая причина оказалась в одном флаге. В базе был включён compile_check=true — это режим разработки Smarty, оставшийся с чьей-то отладки шаблонов. В ядре CS-Cart этот флаг в RenderManager::allowCache() отключает весь блочный кеш, даже когда disable_block_cache стоит правильно. Пока флаг включён, ни один блок (фильтры, навигация, листинг товаров, HTML-блоки) не кешировался — каждая страница пересобиралась с нуля, с десятками тяжёлых SQL_CALC_FOUND_ROWS вместо одного. Один UPDATE в cscart_storage_data — и это был главный фикс.

Полный список того, что сделал в первой фазе:

  • compile_check: true → false — разблокировал весь блочный кеш (главный фикс);
  • disable_block_cache: true → false;
  • key_buffer_size: 16M → 512M — индексы MyISAM (~200 МБ) теперь целиком в RAM;
  • индексы на cscart_products (product_code, company_id);
  • блокировка ботов в nginx;
  • скрипт прогрева кеша, параметризованный по витринам.

Вторая загадка — «то быстро, то медленно». После фикса кеша часть пользователей всё равно ловила 3–5 секунд в случайные моменты. Это оказался не браузерный кеш и не плановая инвалидация, а боты: незаблокированный SemrushBot, ClaudeBot и скрейперы ходили по холодным URL и грели их параллельно. На MyISAM это упирается в table-lock — пока бот собирает холодную страницу под блокировкой таблицы, тёплые категории у живых людей ждут своей очереди. Заблокировал паразитов на всех витринах, оставив поисковые системы и live-AI-поиск; прогрел кеш и снял мониторинг TTFB на сутки для проверки.

Что отбросил и почему. Поставил APCu, но cache_backend сознательно оставил на 'file'. Сайт работает под Apache mpm_itk, где каждый запрос — отдельный процесс со своей изолированной памятью; APCu между запросами не шарится и в этой конфигурации даже медленнее файлового кеша. Замер прямо подтвердил: file = 940 ms против apcu = 1360 ms на той же странице. Модное решение здесь проигрывало — выбрал по числам, а не по моде. Перевод session_backend на 'files' тоже отклонил: этого класса нет в CS-Cart 4.18.3, попытка ломает сайт.

Путь запроса до и после: блочный кеш разблокирован, боты заблокированы — 5–16 секунд превращаются в ~1 секунду

Стек

CS-Cart 4.18.3 · PHP 8.1 · MySQL 8.0 (MyISAM/InnoDB) · nginx · Apache mpm_itk · Smarty · APCu · bash (cache warmup)

Результат

TTFB на прогретом кеше (замеры до/после):

СтраницаБылоСтало
Главная2 709 ms819 ms
Категория /santehnika/smesiteli/8 508 ms~1.0 s
Категория «мебель для ванной»~16 000 ms965 ms
Карточка товара2 018 ms819 ms
Корзина1 374 ms789 ms

Скорость страниц было/стало: TTFB главной, категорий, карточки и корзины — 16 секунд к 1 секунде без апгрейда сервера

Chrome DevTools, вкладка Timing: ожидание ответа сервера на странице категории — 912 мс

Время ответа сервера (TTFB) на странице категории — 912 мс. Замер в Chrome DevTools, вкладка Timing.

По нагрузке сервер на тёплом кеше держит ~100–150 одновременных пользователей / ~15–20k визитов в день — запас под старт рекламы. Всё это без апгрейда тарифа и без переписывания кода: только конфигурация, индексы, защита от ботов и прогрев.

Ограничения и следующий слой. Честно про то, что осталось за рамками этой фазы:

  • Поиск ~3.6–4.9 с — упирается в движок CS-Cart (SQL_CALC_FOUND_ROWS по всему каталогу). До ~1 с доводит только смена движка: FULLTEXT или Searchanise — это отдельное решение.
  • Холодный кеш 3–5 с + MyISAM table-lock остаются архитектурно. Лечатся не latency-тюнингом, а миграцией горячих таблиц на InnoDB (row-level locking) — это дорожная карта, запускается при реальном росте трафика.
  • Тяжёлый DOM ~4.9 МБ на категории — слой фронтенд-темы, отдельный трек, не серверная скорость.

Принцип по этим пунктам один: рычаги под нагрузку (php-fpm pool, InnoDB, Redis-сессии) подключаю при реальном трафике, а не «на всякий случай» — иначе платишь за сложность, которая ещё не нужна.