Начните с одного важного запроса, измерьте путь от клиента до ответа и проверьте гипотезу на сопоставимой нагрузке. Так можно выбрать исправление по фактам.
Сначала определите, какой запрос медленный.
Фраза «API тормозит» слишком широка для исправления. Уточните endpoint, сценарий пользователя, объём данных и момент появления проблемы: всегда, на пике нагрузки или после изменения. Отдельно посмотрите ошибки и таймауты — они могут указывать на иную причину, чем высокая задержка.
- Фиксируйте не только среднее, но и распределение задержек: например, p50, p95 и p99 для важного endpoint.
- Сравнивайте одинаковые условия: запрос, размер ответа, период нагрузки и версию приложения.
- Заранее задайте цель: какой сценарий должен улучшиться и какой компромисс допустим.
Первый артефакт
Один воспроизводимый сценарий и исходная точка измерения. Без них невозможно уверенно оценить эффект исправления.
Разложите время запроса на части.
Нужна трасса (например, OpenTelemetry) или другой способ увидеть путь запроса: приложение, база данных, внешние сервисы, очереди, сериализация и передача ответа. Цель не в том, чтобы собрать максимум графиков, а в том, чтобы обнаружить участок, где теряется время.
01 /
Измерьте снаружи
Зафиксируйте задержку и ошибки глазами клиента или на входе в сервис.
02 /
Сопоставьте внутри
Свяжите медленные запросы с трассами, логами и показателями ресурсов за тот же период.
03 /
Выделите участок
Посмотрите, сколько времени уходит на SQL, внешние вызовы, ожидание, CPU и формирование ответа.
04 /
Проверьте под нагрузкой
Повторите наблюдение на характерной нагрузке: проблема может не проявляться на одиночном запросе.
Практический шаблон
Карта диагностики одного запроса
Шаблон для заполнения по вашей системе. Значения и выводы появляются только после реальных измерений.
Сценарий
Endpoint, действие пользователя, размер ответа и характерная нагрузка.
Исходные показатели
Распределение времени ответа, частота ошибок и момент появления задержки.
Вклад участков
Отдельно оцените SQL, внешние вызовы, ожидание и обработку в приложении.
Проверка изменения
Повторите сценарий на сопоставимой нагрузке; сравните время, ошибки, ресурсы и корректность.
Ищите причину по признакам.
Одинаковая внешняя задержка может иметь разные причины. Поэтому решение выбирают после наблюдения, а не по предпочтению к кэшу, новому фреймворку или языку.
01 / ВАРИАНТ
База данных
Много повторных запросов, тяжёлый план или ожидание блокировок. Проверьте число SQL-вызовов на один запрос к API, журнал медленных запросов и план через EXPLAIN ANALYZE; в PostgreSQL удобна статистика pg_stat_statements.
02 / ВАРИАНТ
Внешний сервис
Время уходит на сетевой вызов, повторы или лимиты партнёра. Проверьте таймауты, параллелизм и необходимость синхронного ответа.
03 / ВАРИАНТ
Приложение и среда
CPU, память, очереди соединений или сериализация. Профиль и ресурсные метрики помогут увидеть точный участок.
Иногда причины складываются: медленный SQL увеличивает время занятости соединения, а затем появляются очереди и таймауты. Тогда требуется устранить первичный источник и снова измерить систему.
Причины, которые легко пропустить
- Очередь PHP-FPM. Когда все воркеры (
pm.max_children) заняты, новые запросы ждут свободного. В логах каждый запрос быстрый, а клиент видит задержку. Проверьте страницу статуса пула (pm.status_path) и счётчикlisten queue. - Пул соединений с базой. Ожидание свободного соединения в метриках приложения выглядит как медленный SQL, хотя сам запрос в базе выполняется быстро.
- Хвостовые задержки. Холодный кэш после выкладки, паузы сборщика мусора, редкие тяжёлые запросы и большие ответы без сжатия заметны в p99, но почти не видны в среднем времени.
Меняйте одну гипотезу и проверяйте эффект.
После диагностики сформулируйте проверяемое изменение: новый индекс, устранение N+1, сокращение внешних вызовов, пересмотр кэширования или настройка конкурентности. Для каждого изменения нужны ожидаемый эффект, тест на корректность и способ возврата назад.
- Сравните исходное и новое поведение на тех же сценариях и нагрузке.
- Следите за побочными эффектами: ошибки, нагрузка на базу, память, стоимость и актуальность данных.
- Оптимизируйте критичный путь, а не только красивый показатель в лаборатории.
Когда нужен Go?
Если измерения показывают ограничение в конкретном участке, Go может быть вариантом реализации. Решение о переносе принимают после сравнения с более локальными изменениями.
Что подготовить для разбора API.
Хватит одного или двух критичных сценариев. Полезны пример запроса без секретов, ожидаемый и фактический диапазон задержки, график ошибок, версия последнего изменения и схема внешних зависимостей. Если трассировка уже есть, приложите несколько типичных медленных трасс.
- Какой endpoint и какой пользовательский сценарий затронут?
- Когда проблема появилась и от чего зависит её частота?
- Какие метрики уже есть, а каких не хватает для решения?