Полгода назад наш основной эндпоинт /products отдавал ответ за 800 мс на p95. Это разбор того, что мы сделали, чтобы довести цифру до 80 мс.
Симптомы
Мониторинг показывал деградацию не постепенно, а скачками — как только в таблицу заказов попадало больше 200k строк, время ответа каталога подскакивало вдвое.Диагностика
Включили
pg_stat_statementsи нашли топ по total_timeОбнаружили классический N+1: категория и вендор подгружались отдельным запросом на каждый продукт
Отсутствовал составной индекс на
(delivery_type, is_active, created_at)
Что исправили
Заменили последовательные Preload на GORM на явные JOIN'ы через VIEW product_catalog, добавили частичные индексы под самые частые фильтры каталога и вынесли подсчёт total_downloads в денормализованное поле с фоновым пересчётом.
Индекс — это не бесплатно: каждый лишний индекс замедляет запись. Мы удалили три неиспользуемых индекса, прежде чем добавлять новые.
Результат
p95 упал с 800 до 80 мс, нагрузка на CPU базы снизилась почти вдвое. Полный список миграций — в репозитории проекта.

