# 13. Производительность

Как работать с latency, throughput, профилированием, кэшированием и performance budgets без преждевременной оптимизации.

- **Author:** Фёдор Чищин
- **Level:** advanced
- **Reading time:** ~25 минут чтения
- **Published:** 2026-05-23
- **Source:** https://fedorthinks.com/ru/learn/software-architect-13-performance

---

## 1. Главная идея

Оптимизировать нужно bottleneck, а не место, которое просто выглядит некрасиво.

### Latency и throughput — разные вещи

> Такси быстро довозит одного человека. Метро перевозит тысячи. Сравнивать их одним словом «быстро» бессмысленно.

Latency — время ответа для одной операции. Throughput — сколько операций система обрабатывает за период. Можно снизить latency одного запроса и ухудшить throughput всей системы, например агрессивным parallelism без контроля ресурсов.

Архитектор должен формулировать performance requirement конкретно: p95 response time, p99 tail latency, requests per second, batch duration, cold start, memory budget. «Должно быть быстро» не является требованием.

### Кэш — это ответственность за устаревание

> Копия меню на витрине полезна, пока цены совпадают с кассой. Потом она становится источником конфликтов.

Caching ускоряет чтение, но добавляет invalidation, TTL, consistency model и риск stale data. Перед кэшем стоит спросить: что именно дорого, как часто меняется, можно ли показать устаревшее значение, как сбросить кэш при изменении source of truth.

Кэшировать без понимания модели данных опасно: можно ускорить неправильный ответ.

## 2. Пример и антипример

Хорошая оптимизация начинается с измерения и заканчивается проверкой результата.

### Пример: slow endpoint через профилирование

> Врач сначала ставит диагноз, а не сразу назначает операцию, потому что пациент сказал «где-то болит».

Endpoint `/dashboard` имеет p95 2.8 секунды. Tracing показывает: 80% времени уходит на N+1 запросы к базе и отсутствие индекса по `workspace_id, created_at`. Команда добавляет eager loading, индекс и performance test.

Результат: p95 становится 380 ms. Решение точечное, измеримое и не добавляет лишнюю архитектурную сложность.

### Антипример: переписать на Go без профиля

> Поменять двигатель бессмысленно, если машина стоит в пробке из-за закрытой дороги.

Команда решает переписать сервис на другой язык, потому что «Python медленный». Позже выясняется, что 90% времени занимали внешние API и плохо спроектированные SQL-запросы.

Язык может быть bottleneck, но это нужно доказать. Иначе оптимизация превращается в дорогой refactor без бизнес-эффекта.

#### Самопроверка

- Какая метрика performance важна именно здесь?
- Где bottleneck по данным profiler/tracing?
- Какой budget считается приемлемым?
- Что сломается при кэшировании?

Следующий модуль: [Масштабируемость](./software-architect-14-scalability).
