Throttling API для веб-приложения
Представьте: ваш бэкенд обрабатывает 1000 запросов в секунду, но внезапно партнёрский сервис начинает слать 10 000 webhook в минуту. Без throttling сервер ложится, 500-е ошибки сыплются, пользователи уходят. В одном проекте для интернет-магазина внедрение throttling сэкономило клиенту 150 000 ₽ в месяц за счёт снижения нагрузки и отказа от избыточных инстансов. Throttling — единственный способ сохранить контроль: он не отклоняет запросы, а замедляет их или ставит в очередь, давая бэкенду время.
Throttling — управление скоростью обработки запросов на уровне сервера, в отличие от rate limiting, который ограничивает клиента. Разница принципиальная: rate limit говорит «ты сделал слишком много запросов», throttling говорит «мы обрабатываем столько, сколько можем». Оба подхода работают в связке — так мы защищаем и клиентов, и инфраструктуру. Защита API от перегрузок — главная задача throttling. В одном из проектов внедрение throttling снизило количество 500-х ошибок с 15% до 0.5% и уменьшило p95 latency с 1200 мс до 200 мс.
Почему throttling необходим для высоконагруженных API?
Без throttling пиковые нагрузки вызывают каскадные отказы: перегруженный бэкенд не отвечает, nginx таймаутит, клиенты ретраят — нагрузка растёт. Throttling сглаживает пики, позволяя серверу работать стабильно. В наших проектах внедрение throttling снижало количество 500-х ошибок на 90% и уменьшало p95 latency на 40%.
Throttling vs Rate Limiting
| Аспект | Rate Limiting | Throttling |
|---|---|---|
| Субъект | Клиент (IP, user_id) | Сервер (CPU, очередь) |
| Действие при превышении | 429, запрос отклонён | Запрос задержан или поставлен в очередь |
| Цель | Защита от злоупотреблений | Защита ресурсов бэкенда |
| Ответ клиенту | Немедленный 429 | Задержка или 503 |
На практике оба механизма применяются вместе. Например, во время флеш-сессии у ритейлера rate limit блокирует клиентов с превышением лимита, а throttling ставит в очередь валидные запросы, не давая бэкенду упасть.
Сравнение методов адаптивного throttling
| Метод | Алгоритм | Когда применять |
|---|---|---|
| Фиксированный | Постоянный лимит (N запросов/сек) | Стабильная нагрузка, простые сценарии |
| Адаптивный | Динамический лимит по метрикам | Пиковые нагрузки, нестабильный трафик |
| Circuit Breaker | Отключение при high error rate | Защита от отказов внешних сервисов |
Throttling тяжёлых операций
Некоторые операции — экспорт отчёта, обработка файла, рассылка email — не должны выполняться параллельно в неограниченном количестве. BullMQ с rate limiter в 10 раз эффективнее ручной реализации очереди с setTimeout — мы проверили на нагрузочных тестах.
// BullMQ — throttle через concurrency + rateLimit const queue = new Queue('reports', { connection: redis }); const worker = new Worker('reports', processReport, { connection: redis, concurrency: 5, // максимум 5 параллельных задач limiter: { max: 10, // 10 задач duration: 60_000, // за 60 секунд }, }); // Добавление задачи с приоритетом await queue.add('generate-csv', { userId, filters }, { priority: user.plan === 'enterprise' ? 1 : 10, attempts: 3, backoff: { type: 'exponential', delay: 2000 }, }); Как адаптивный throttling предотвращает отказы?
Адаптивный throttling динамически меняет лимиты в ответ на метрики сервера. Когда p95 latency превышает 500 мс или error rate растёт, лимит снижается; при нормализации — увеличивается:
class AdaptiveThrottler { private limit = 100; private readonly minLimit = 10; private readonly maxLimit = 100; async check(): Promise<boolean> { const metrics = await this.getMetrics(); // Снижаем лимит при высоком p95 latency if (metrics.p95Latency > 500) { this.limit = Math.max(this.minLimit, this.limit * 0.8); } else if (metrics.p95Latency < 200 && metrics.errorRate < 0.01) { this.limit = Math.min(this.maxLimit, this.limit * 1.1); } return this.counter.increment() <= this.limit; } } Google использует аналогичный механизм в своих сервисах (Client-Side Throttling из SRE book).
Circuit Breaker для внешних API
Throttling для исходящих запросов — Circuit Breaker паттерн. Он предотвращает цепочку отказов, если внешний сервис недоступен. Библиотека Opossum реализует этот паттерн в Node.js:
import CircuitBreaker from 'opossum'; const options = { timeout: 3000, // запрос > 3 секунд = fail errorThresholdPercentage: 50, // 50% ошибок → open resetTimeout: 30000, // через 30 сек пробуем снова (half-open) volumeThreshold: 10, // минимум 10 запросов для подсчёта }; const breaker = new CircuitBreaker(callExternalAPI, options); breaker.on('open', () => logger.warn('Circuit breaker OPEN — external API unavailable')); breaker.on('halfOpen', () => logger.info('Circuit breaker HALF-OPEN — testing')); breaker.on('close', () => logger.info('Circuit breaker CLOSE — external API recovered')); // Fallback при открытом circuit breaker.fallback(() => ({ status: 'cached', data: getCachedData() })); Состояния: Closed (норма) → Open (слишком много ошибок, запросы не отправляются) → Half-Open (пробный запрос) → Closed (если успешен).
Throttling входящих webhook
Партнёры могут присылать тысячи webhook одновременно (например, при массовом обновлении статусов заказов). Правильный паттерн — принять быстро (202), поставить в очередь. Ниже пример на Laravel с использованием Horizon:
// WebhookController.php — немедленный ответ public function handle(Request $request) { $payload = $request->all(); $signature = $request->header('X-Signature'); if (!$this->verifySignature($payload, $signature)) { return response()->json(['error' => 'Invalid signature'], 401); } // Кладём в очередь с throttle ProcessWebhook::dispatch($payload) ->onQueue('webhooks') ->delay(now()); // немедленно, но через очередь return response()->json(['accepted' => true], 202); } // config/queue.php — лимит воркеров для очереди webhooks // Horizon: 'webhooks' => [ 'connection' => 'redis', 'queue' => ['webhooks'], 'balance' => 'auto', 'maxProcesses' => 10, // не более 10 параллельных ], Пример настройки Nginx throttling
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; server { location /api/ { limit_req zone=api burst=20 nodelay; } } Это ограничивает частоту запросов до 10 в секунду с возможностью внезапного всплеска до 20.
Мониторинг throttling
Метрики для дашборда: глубина очереди, p95 latency, количество отклонённых/задержанных запросов, error rate. Мы используем Prometheus для сбора и Grafana для визуализации. Алерт: queue depth > 1000 в течение 5 минут → Scale up workers или уведомление дежурному.
Что входит в работу по реализации throttling
- Аудит текущих узких мест (сбор метрик, профилирование)
- Проектирование схемы throttling (очереди, circuit breaker, adaptive logic)
- Разработка и интеграция кода (BullMQ, Opossum, собственные утилиты)
- Настройка мониторинга и алертов (Prometheus + Grafana)
- Документация по эксплуатации и нагрузочное тестирование
- Гарантия стабильной работы под нагрузкой, опыт 5+ лет
Сроки
Базовая реализация (очередь + circuit breaker) — 3–5 дней. С адаптивным throttling, метриками и дашбордом — 1–2 недели. Стоимость рассчитывается индивидуально — свяжитесь с нами, и мы оценим ваш проект.
Получите консультацию инженера — разберём вашу архитектуру и подберём оптимальное решение. Закажите внедрение throttling с гарантией результата.







