Интернет-магазин на CS-Cart (58 000 товаров): TTFB 16 → 1 секунда без апгрейда сервера
Магазин сантехники на CS-Cart (~58k товаров) грузился 12–16 с. Причина — не сервер, а забытый флаг разработки, отключивший кеш. Диагностика вернула TTFB к ~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, попытка ломает сайт.

Стек
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 ms | 819 ms |
Категория /santehnika/smesiteli/ | 8 508 ms | ~1.0 s |
| Категория «мебель для ванной» | ~16 000 ms | 965 ms |
| Карточка товара | 2 018 ms | 819 ms |
| Корзина | 1 374 ms | 789 ms |


Время ответа сервера (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-сессии) подключаю при реальном трафике, а не «на всякий случай» — иначе платишь за сложность, которая ещё не нужна.