# Ru

> Полный аудит производительности и ресурсоёмкости всего репозитория the-platform (backend-сервисы FastAPI/asyncpg/PostgreSQL/Redis/RabbitMQ, the-frontend, общие библиотеки libs/*, Docker/Kubernetes/Helm инфраструктура, нагрузочное тестирование k6 в load-testing/) — три независимых среза (инструментальное профилирование, построчный код-ревью, архитектурный обзор), находки только с измерением (EXPLAIN ANALYZE, py-spy, размер бандла, k6-прогоны), severity, file:line и итоговым вердиктом. Используй когда просят провести аудит производительности/ресурсоёмкости всей кодовой базы или инфраструктуры целиком, проверить расход CPU/RAM/сетевого трафика/стоимости инфраструктуры, найти узкие места по всему репозиторию, оценить экономичность архитектуры при росте нагрузки, или повторно перепроверить статус находок из предыдущего аудита/load-testing отчётов — даже если пользователь не произносит слово "аудит" буквально, а говорит "почему сервис жрёт столько CPU/памяти", "давай посмотрим на производительность всего проекта" и

- Skill: `smirnovalex-qa/ru-27` (Agent Skill)
- Install (CLI): `npx skillmds@latest add smirnovalex-qa/ru-27`
- Raw SKILL.md: https://api.skillmd.com/api/skills/smirnovalex-qa/ru-27/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: smirnovalex-qa (https://skillmd.com/u/smirnovalex-qa)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/smirnovalex-qa/ru-27

---

# Полный аудит производительности и ресурсоёмкости репозитория

Для проекта the-platform: микросервисная CRM-платформа — FastAPI + asyncpg +
PostgreSQL + Redis + RabbitMQ бэкенд-сервисы, React/Vite/TS фронтенд
(the-frontend), Docker/Kubernetes/Helm инфраструктура, нагрузочное
тестирование на k6 в `load-testing/`.

## РОЛЬ

Компания, для которой делается продукт, крайне чувствительна к расходу
вычислительных ресурсов (CPU, RAM, сетевой трафик, стоимость инфраструктуры)
— производительность и экономичность рассматриваются как приоритет первого
класса, а не как техдолг "когда-нибудь потом". Аудит должен находить
реальные, измеримые проблемы с привязкой к file:line и количественной
оценкой воздействия (латентность, CPU, RAM, число запросов к БД, размер
трафика), а не составлять общий чек-лист "best practices" без проверки на
конкретной кодовой базе.

## ВХОДНЫЕ ДАННЫЕ

`$ARGUMENTS` — необязательно путь к отчёту предыдущего аудита или к
load-testing/reports для сравнения "было → стало". Если не передан — ищи
сам: `load-testing/ANALYSIS_GUIDE.md`, `load-testing/reports`, и любые
предыдущие отчёты аудита производительности, упомянутые в диалоге или
репозитории.

Это аудит ВСЕГО репозитория. Если задача на самом деле касается только
одной фичи/ветки/PR — это не тот скилл, используй `performance-audit-feature`
вместо полного разбора всей кодовой базы (иначе периметр окажется избыточным
и находки не будут привязаны к тому, что реально важно проверить).

## КЛЮЧЕВОЙ ПРИНЦИП: ИЗМЕРЯЙ, А НЕ ДОГАДЫВАЙСЯ

Главная причина, по которой аудиты производительности проваливаются или,
наоборот, наносят вред — это два симметричных провала: (а) находки без
доказательства реального воздействия ("это может быть медленно") и (б)
слепое накручивание "оптимизаций" (кэширование, мемоизация,
denormalization) там, где нет измеренной проблемы, что усложняет код и
создаёт новый класс багов (протухший кэш, race condition) ради
несуществующего выигрыша. Обоих провалов быть не должно:

1. Для каждой находки, где это технически возможно, подтверждай воздействие
   измерением: EXPLAIN ANALYZE для SQL-запроса, профилирование
   (py-spy/cProfile) для CPU-хотспота, реальный размер бандла для
   фронтенда, вывод существующих k6-сценариев из `load-testing/` для
   нагрузочных характеристик API. Находка без числа — гипотеза, а не
   находка; помечай её явно как "не подтверждено измерением" и указывай,
   что нужно для подтверждения.
2. Не предлагай оптимизацию там, где нет доказанной проблемы. Если код
   "неидиоматичен", но не находится на горячем пути и не потребляет
   заметных ресурсов — фиксируй как cosmetic/low, не как performance-
   находку. Три одинаковых строки лучше преждевременной абстракции; тот же
   принцип применим к кэшам и мемоизации.
3. Различай "теоретически неоптимально" и "реально дорого при
   текущем/ожидаемом объёме данных". N+1 запрос на таблице с 10 строками в
   dev-окружении — не то же самое, что N+1 на таблице контактов/сделок с
   сотнями тысяч строк в проде. Явно указывай, при каком объёме данных
   находка становится критичной.
4. Если оптимизация уже была сделана раньше (проверь git log/комментарии) —
   проверь, не регрессировала ли она позже (например, кэш добавили, но
   инвалидацию забыли при рефакторинге соседнего модуля).
5. Формулируй статус явно: "подтверждено измерением" / "правдоподобно, но
   не измерено" / "не является проблемой при текущем объёме данных" / "уже
   оптимизировано корректно".

## МЕТОДОЛОГИЯ: ТРИ НЕЗАВИСИМЫХ СРЕЗА

Проведи аудит тремя независимыми методами и не позволяй одному срезу
подменять другой — у них разная слепая зона.

### СРЕЗ 1 — Инструментальный анализ и профилирование

- **Backend (Python/FastAPI)**: включи логирование SQL (echo=True/aiosqlalchemy
  debug) на ключевых сценариях и найди N+1 запросы и запросы без
  LIMIT/пагинации; там, где доступно подключение к БД — прогони EXPLAIN
  ANALYZE на самых частых/тяжёлых запросах и зафиксируй отсутствие индексов
  (seq scan там, где ожидается index scan); используй py-spy/cProfile для
  профилирования CPU на подозрительных горячих путях (webhook-обработчики,
  sync-джобы, сериализация больших ответов).
- **База данных**: pg_stat_statements (если включён) для топ запросов по
  суммарному времени и по числу вызовов; список таблиц без индексов на
  колонках, используемых в WHERE/JOIN/ORDER BY (сверь со схемой миграций
  каждого сервиса); размер таблиц и рост со временем, если есть доступ к
  метрикам.
- **Redis**: паттерны ключей без TTL (риск неограниченного роста памяти),
  команды KEYS/SCAN по всему пространству ключей в хот-пасе, размер
  значений (сериализация целых объектов вместо нужных полей).
- **RabbitMQ**: конфигурация prefetch/QoS, глубина очередей, retry-политики
  без backoff/DLQ.
- **Docker-образы**: dive или `docker history` по каждому собираемому
  образу — размер слоёв, неиспользуемые build-инструменты и
  dev-зависимости, попавшие в финальный образ; сравни с multi-stage build
  там, где он есть/отсутствует.
- **Frontend (the-frontend)**: построй production-сборку и проанализируй
  бандл (`vite build --mode production` + rollup-plugin-visualizer/
  source-map-explorer, если подключены, либо разбор dist/ по размеру
  чанков вручную); Lighthouse (или аналог) по ключевым страницам для
  метрик LCP/TBT/bundle size, если есть возможность поднять фронтенд
  локально.
- **Нагрузочное тестирование**: в репозитории уже есть k6-сценарии и
  отчёты в `load-testing/` (см. `load-testing/ANALYSIS_GUIDE.md`,
  `load-testing/k6`, `load-testing/reports`). Прочитай существующие
  отчёты — какие узкие места уже были найдены ранее и не устранены; если
  возможно поднять окружение — прогони актуальные сценарии заново и
  сравни с сохранёнными baseline-отчётами.
- **Kubernetes/Helm**: checkov/kube-linter или ручной разбор чартов на
  предмет resources requests/limits (пустые/отсутствующие — риск noisy
  neighbor и throttling; завышенные — прямой перерасход бюджета на
  инфраструктуру), интервалы liveness/readiness проб (слишком частые
  пробы = постоянная фоновая нагрузка на N реплик), конфигурация HPA и её
  пороги.

### СРЕЗ 2 — Ручной построчный разбор кода

Раздели кодовую базу на независимые зоны и разбери КАЖДУЮ (не по диагонали,
не полагаясь только на grep-паттерны):

- Каждый backend-сервис отдельно (gateway, все `*-service` директории в
  `services/`).
- Frontend / SPA (`the-frontend`).
- Фоновые обработчики, боты и интеграции с внешними API
  (telegram-bot-service, telegram-connector-service,
  whatsapp-personal-service, kommo-integration-service,
  verification-bot-service, ai-bot-service) — это код с наибольшим риском
  постоянной фоновой нагрузки (поллинг, синки, long-polling), а не только
  запрос-ответ по требованию.
- Общие библиотеки (`libs/shared_auth`, `libs/shared_metrics`) — код,
  который выполняется на КАЖДОМ запросе КАЖДОГО сервиса; даже небольшая
  неэффективность здесь умножается на количество сервисов и реплик.
- Инфраструктурные конфиги (`helm/`, `docker-compose*.yml`, `deploy/`,
  `infrastructure/`).

По каждой зоне ищи (детальный чек-лист ниже) и для каждой находки
указывай: file:line, тип проблемы, количественную оценку воздействия (или
пометку "не измерено"), severity, статус (см. выше).

### СРЕЗ 3 — Архитектурный обзор

Независимо от построчного разбора оцени, способна ли текущая архитектура
УДЕРЖИВАТЬ экономичность при росте нагрузки, а не только не иметь явных
проблем сегодня:

- "Болтливая" межсервисная архитектура: сколько последовательных
  синхронных HTTP-вызовов делает один пользовательский запрос через
  gateway → сервисы → сервисы (построй цепочку для 2-3 самых частых
  сценариев: логин, список сделок/лидов, отправка сообщения в чат). Каждый
  лишний хоп — это латентность и CPU/сеть, умноженные на трафик.
- Оправданность фиксированного числа реплик (в
  `docker-compose.microservices.yml` gateway поднят в 3 экземплярах и
  т.п.) — есть ли данные о реальной нагрузке, оправдывающие это число, или
  это "на всякий случай"? То же для аналогичных решений в helm-values
  (replicaCount).
- Дублирование общих библиотек (shared_auth, shared_metrics) по сервисам
  вместо единого пакета — если производительный фикс/оптимизация сделаны в
  одной копии, распространяется ли это автоматически на остальные, или
  патч придётся катить N раз (тот же риск, что и для security-патчей).
- Общая стратегия кэширования: есть ли она вообще как осознанное решение
  (что кэшируется, на каком уровне, с какой инвалидацией), или кэш
  добавляется точечно и бессистемно там, где кто-то один раз заметил
  тормоза.
- Совмещение OLTP-нагрузки (транзакционные сервисы) и тяжёлой аналитики
  (Superset, analytics-service) на одной БД/инстансе — конкуренция за
  ресурсы.
- Наличие процесса: прогоняется ли нагрузочное тестирование (k6 в
  `load-testing/`) регулярно или разово; есть ли бюджет производительности
  (performance budget) для фронтенд-бандла и API-латентности, закреплённый
  в CI, а не только "по ощущениям".

## ДЕТАЛЬНЫЙ ЧЕК-ЛИСТ ПО КАТЕГОРИЯМ

1. **Асинхронный backend: блокирующие вызовы в event loop** — синхронные
   HTTP-клиенты (requests и т.п.) вместо httpx.AsyncClient/aiohttp внутри
   async-обработчиков; синхронный I/O (открытие файлов, time.sleep,
   синхронные драйверы БД) внутри async def; CPU-тяжёлые операции (парсинг
   больших JSON/XML, шифрование, обработка изображений) на event loop без
   ThreadPoolExecutor/ProcessPoolExecutor; последовательные `await` там,
   где вызовы независимы и могли бы идти параллельно через
   `asyncio.gather` (типичный паттерн в gateway при обращении к нескольким
   сервисам для сборки одного ответа).
2. **База данных (PostgreSQL)** — N+1 запросы (цикл с запросом к БД
   внутри, где можно один JOIN/`selectinload`/`joinedload`); отсутствующие
   индексы на колонках в WHERE/ORDER BY/JOIN, особенно на внешних ключах
   (user_id, tenant_id, integration_id) и мультитенантной фильтрации;
   `SELECT *`/полная сериализация там, где нужны 2-3 поля; списковые
   эндпоинты без пагинации/LIMIT; размер пула соединений относительно
   числа реплик и лимита PostgreSQL; долгие транзакции с внешними
   HTTP-вызовами внутри (категорически недопустимый паттерн); повторяющиеся
   идентичные запросы в рамках одного request-response цикла.
3. **Кэширование (Redis)** — ключи без TTL; отсутствие кэша для дорогих
   часто повторяющихся и редко меняющихся вычислений (агрегаты дашбордов,
   справочники, роли); cache stampede (нет lock/single-flight при
   протухании); кэш без инвалидации при изменении исходных данных
   (фиксируй отдельно как корректностную, не только perf-проблему);
   KEYS/SCAN по всей базе в хот-пасе, хранение больших блобов вместо
   специализированного хранилища.
4. **Межсервисное взаимодействие (HTTP)** — отсутствие таймаутов на
   исходящих запросах; отсутствие retry с exponential backoff (либо retry
   без backoff — thundering herd при частичном инциденте); дублирующие
   вызовы одного сервиса вместо batched-вызова; полная пересылка тяжёлых
   payload там, где нужна часть данных.
5. **Очереди (RabbitMQ) и фоновые обработчики** — prefetch/QoS (слишком
   большой перегружает консьюмера, слишком маленький недоиспользует
   параллелизм); poison message без DLQ; частота поллинга внешних API
   (kommo-integration-service, telegram-connector-service,
   whatsapp-personal-service) относительно реальной потребности, размер
   батча, обработка rate-limit (429/ретраи).
6. **Сериализация и размер payload** — Pydantic-модели, возвращающие
   значительно больше полей, чем реально используется; логирование
   целиком крупных объектов/payload в hot path; отсутствие сжатия
   (gzip/brotli) на gateway для крупных JSON-ответов.
7. **Frontend (React/Vite/TS)** — размер production-бандла и отсутствие
   code-splitting/lazy-loading для редко используемых маршрутов;
   неоптимизированные изображения/статические ассеты; избыточные
   ре-рендеры на больших списках/таблицах (лидов/сделок) — отсутствие
   виртуализации, новые объекты/колбэки в render без memo там, где
   профайлер явно показывает горячую точку (не добавляй memo/useCallback
   повсеместно "на всякий случай" — это тоже стоит ресурсов без измеренной
   пользы); waterfall-загрузка данных вместо параллельной; слишком частый
   polling там, где уместнее WebSocket/SSE, либо WebSocket с избыточными
   reconnect/heartbeat.
8. **Docker-образы** — размер финального образа по каждому Dockerfile
   (services/*, the-frontend); отсутствие multi-stage build там, где
   build-зависимости попадают в финальный слой; избыточный базовый образ
   (full OS вместо slim/alpine/distroless), если это не создаёт проблем
   совместимости.
9. **Kubernetes/Helm** — resources requests/limits: отсутствующие (noisy
   neighbor, OOM-kill) и одновременно завышенные "с запасом" без основания
   на реальном потреблении; интервалы/таймауты liveness/readiness/startup
   проб на большое число реплик; replicaCount и HPA-пороги — обоснованы ли
   числами; init-контейнеры и стартовая логика подов — не блокируют ли
   готовность дольше необходимого.
10. **Наблюдаемость как источник накладных расходов** — кардинальность
    метрик (shared_metrics): лейблы с высокой кардинальностью (user_id,
    request_id как label вместо значения); частота/объём сэмплирования
    трейсов; объём и уровень логирования в проде (DEBUG-логи "для
    удобства"); синхронная отправка метрик/трейсов в hot path вместо
    батчинга/асинхронной отправки.
11. **Алгоритмическая эффективность и структуры данных** — квадратичные и
    худшие по сложности операции над коллекциями, которые на реальных
    объёмах данных станут узким местом (списки лидов/контактов/сообщений
    чата растут со временем); повторный парсинг/пересчёт одних и тех же
    данных в рамках одного запроса; ненужное глубокое копирование крупных
    структур; отсутствие батчинга для массовых операций (импорт лидов,
    синки с внешними CRM) там, где объём операций регулярно велик.
12. **Нагрузочное тестирование и бюджеты производительности** —
    актуальность k6-сценариев (load-testing/k6) относительно текущих
    API-контрактов; расхождение между узкими местами, задокументированными
    в load-testing/reports и load-testing/ANALYSIS_GUIDE.md, и текущим
    состоянием кода (исправлены ли они на самом деле, или отчёт остался
    неактуализированным — "исправлено на бумаге"); наличие или отсутствие
    зафиксированных бюджетов производительности в CI (максимальный размер
    бандла, максимальная латентность p95) — без такого гейта регрессии
    производительности проникают в прод незамеченными.

## EDGE CASES, КОТОРЫЕ ЧАСТО ПРОПУСКАЮТ

- "На dev-данных работает быстро" — проблема проявляется только на
  реальных объёмах данных клиента (тысячи лидов, десятки тысяч сообщений в
  чате); всегда прикидывай ожидаемый рост.
- Отладочные удобства, забытые в проде: verbose-логирование, отключённое
  сжатие ответов, отключённый кэш "чтобы было проще дебажить" — и не
  включённые обратно.
- Health/readiness-пробы, дёргающие БД или внешние сервисы на каждой
  N-секундной проверке, умноженные на число реплик — суммарно заметная
  фоновая нагрузка на БД без бизнес-пользы.
- Несколько независимых сервисов, опрашивающих один и тот же внешний API
  дублирующим образом вместо общего кэша/единой точки синхронизации.
- Retry-логика без backoff, усиливающая нагрузку именно в момент
  частичного инцидента (когда ресурсы и так в дефиците).
- Тяжёлые аналитические запросы (Superset/analytics-service),
  выполняющиеся на той же БД/инстансе, что и транзакционная нагрузка, в
  часы пиковой нагрузки на CRM.
- "Оптимизация ради оптимизации": кэш/мемоизация/денормализация,
  добавленные без измеренной проблемы — увеличивают сложность и объём
  кода, который надо содержать и который сам потребляет ресурсы (память
  кэша, синхронизация), без доказанной выгоды. Фиксируй и такие находки —
  предлагай упрощение.
- Различия конфигурации между окружениями (dev/staging/prod) в
  docker-compose/helm-values — оптимизация, сделанная для одного
  окружения, может отсутствовать в другом.
- Забытые после экспериментов feature flags, удваивающие работу (пишем в
  старую и новую систему одновременно "на время миграции", которая давно
  завершилась).

## ФОРМАТ ОТЧЁТА

1. Executive summary (для руководства, без технического жаргона): что
   расходует ресурсы заметнее всего, что можно оптимизировать без риска
   для функциональности в первую очередь, ориентировочный эффект (в
   терминах латентности/нагрузки/инфраструктурных ресурсов).
2. Таблица KPI: число находок по severity (critical/high/medium/low),
   число находок, подтверждённых измерением, vs "правдоподобно, но не
   измерено"; ориентировочная суммарная экономия ресурсов при устранении
   критичных находок, если её можно оценить.
3. Если это повторный аудит — таблица сопоставления "пункт предыдущего
   отчёта/load-testing отчёта → текущее состояние (file:line) → статус (не
   исправлено / формально / выборочно / исправлено)".
4. Раздел "исправлено, но не работает" отдельно (например: индекс добавлен
   в миграции, но запрос всё равно делает seq scan из-за несовпадения
   типов/функции в WHERE).
5. Полный список находок с привязкой file:line, количественной оценкой
   воздействия (или явной пометкой "не измерено" и что нужно для
   измерения), severity и конкретной рекомендацией по исправлению (не
   "оптимизировать запрос", а "добавить индекс на (tenant_id,
   created_at)", "заменить N+1 на selectinload", "вынести вызов внешнего
   API из тела транзакции").
6. Раздел "что сделано хорошо" — эффективные паттерны в кодовой базе,
   которые стоит тиражировать на другие сервисы, а не переделывать.
7. План действий по срокам: быстрые точечные фиксы без риска регрессии
   (индексы, таймауты, исправление N+1) — в первую очередь; изменения,
   требующие тестирования под нагрузкой — во вторую; архитектурные решения
   (пересмотр стратегии кэширования, сокращение числа межсервисных хопов,
   план масштабирования) — как решения уровня руководства/тимлидов.
8. Раздел "методология и ограничения покрытия" — какие инструменты и
   измерения были использованы, какие сервисы/зоны НЕ были профилированы
   или нагружены и почему (нет доступа к прод-метрикам, нет возможности
   поднять окружение и т.п.), чтобы отсутствие находок в непокрытой зоне
   не читалось как "там всё оптимально".

## ПРАВИЛА ОФОРМЛЕНИЯ НАХОДОК

Для каждой находки обязательны:

- Путь к файлу и номер строки (или диапазон).
- Название проблемы и категория (см. чек-лист выше).
- Количественная оценка воздействия: измеренная (число запросов к БД,
  EXPLAIN ANALYZE вывод, время профилирования, размер бандла/образа в МБ,
  латентность p50/p95) либо явно помеченная как неизмеренная оценка с
  обоснованием, почему она вероятна.
- Условие, при котором проблема становится критичной (объём данных, число
  одновременных пользователей, частота вызова) — если оно не выполняется
  сегодня, но выполнится при росте, укажи это явно, не занижай и не
  завышай срочность.
- Severity с обоснованием (какая доля трафика/данных затронута, какой
  ресурс расходуется: CPU, RAM, сетевой трафик, число соединений с БД,
  стоимость инфраструктуры).
- Статус относительно предыдущего аудита/load-testing отчёта, если
  применимо.
- Рекомендация по исправлению — конкретная и с сохранением текущей
  функциональности (аудит не должен предлагать менять поведение системы,
  только эффективность его реализации).

## ЗАПУСК АУДИТА (практическая инструкция)

1. Определи периметр: перечисли все backend-сервисы (services/*), фронтенд
   (the-frontend), общие библиотеки (libs/*), фоновые боты/коннекторы,
   инфраструктурные конфиги (helm/, docker-compose*.yml, deploy/,
   infrastructure/), существующие нагрузочные тесты (load-testing/).
2. Прочитай существующие артефакты нагрузочного тестирования
   (load-testing/ANALYSIS_GUIDE.md, load-testing/reports) ПЕРЕД началом
   ручного разбора — это готовый источник уже известных узких мест, не
   дублируй работу, а проверь, устранены ли они.
3. Запусти доступные инструменты СРЕЗА 1 по каждому сервису/образу/чарту,
   где это возможно в текущем окружении; сохрани сырой вывод для
   приложений к отчёту.
4. Раздели ручной разбор СРЕЗА 2 на независимые куски (по сервису/зоне) —
   если доступен Agent tool, запусти несколько независимых субагентов на
   разные зоны параллельно (в foreground, если результат нужен сразу в
   этом диалоге), чтобы не пропустить объём и не дать одному агенту
   "срезать угол" по всей кодовой базе разом.
5. Проведи архитектурный обзор СРЕЗА 3 отдельно, независимо от результатов
   среза 2.
6. Сведи все три среза в единый отчёт по формату выше, убери дубликаты, но
   не объединяй находки разной природы (инструмент нашёл подозрительный
   паттерн ≠ ручной разбор подтвердил реальное воздействие — фиксируй оба
   факта, если они есть, с соответствующим статусом подтверждения).
7. Если это повторный аудит — обязательно перепроверь КАЖДЫЙ пункт
   предыдущего отчёта и каждую находку из load-testing/reports по текущему
   состоянию кода, а не полагайся на статус, заявленный командой.
8. Явно укажи, какие проверки НЕ были выполнены (нет доступа к
   прод-метрикам/pg_stat_statements, нет возможности поднять окружение для
   профилирования или прогона k6, нет данных о реальных объёмах клиентских
   данных) — это часть честного отчёта, а не его слабость.
9. Ни одна рекомендация не должна менять наблюдаемое поведение/
   функциональность системы — только эффективность реализации. Если для
   оптимизации неизбежно требуется изменение поведения (например,
   ужесточение пагинации по умолчанию) — отметь это отдельно и явно.

Это аудит, не имплементация: правки вносит разработчик по итогам отчёта,
не ты в рамках этого скилла.

