AI-инжиниринг

Rate Limiting для AI API: token bucket, sliding window, per-user quotas

Цели урока

  • Понять разницу между RPM и TPM rate limiting для LLM API
  • Реализовать Token Bucket алгоритм с двумя измерениями: запросы и токены
  • Построить per-user quota систему с Redis для справедливого распределения ресурсов
  • Создать NestJS Guard, объединяющий global rate limit и per-user quotas

OpenAI rate limit: 10,000 RPM для tier 3. Звучит много. Один пользователь с automation-скриптом - 600 запросов в минуту. 17 таких - и весь аккаунт лежит. Rate limiting для AI - это не про 429 ошибки, это про token budget по пользователям.

  • OpenAI tier system: tier 1 даёт 500 RPM и 30,000 TPM. Один RAG-запрос с 8K контекстом = 8,000 TPM. После 3 таких запросов одновременно - лимит исчерпан для всех
  • Anthropic ограничивает tier 1 до 50 RPM и 40,000 TPM с суточным лимитом в 1000 запросов - без per-user квот один активный пользователь обнулит день
  • ChatGPT использует per-user rate limiting: 'You've reached the limit on messages' - это тот же token budget, только в интерфейсе
  • Vercel AI SDK включает встроенный rate limiter с Redis-backed token counting - индустрия признала проблему стандартной

От сетевых алгоритмов к квотам LLM

Rate limiting появился задолго до AI. Алгоритмы **token bucket** и **leaky bucket** пришли из классического networking и traffic shaping, где они сглаживали всплески и удерживали средний темп на роутерах и свитчах. Те же алгоритмы теперь управляют LLM API в виде лимитов RPM (requests per minute) и TPM (tokens per minute). Особенность для AI в том, что стоимость и нагрузка растут от числа токенов, а не только от числа запросов, поэтому старые bucket'ы применяют к токен-бюджету на пользователя, а не только к частоте запросов.

Предварительные знания

  • LLM API Integration: OpenAI, Anthropic, Open-Source Models

Почему rate limiting для AI API отличается от обычного

OpenAI tier 3: 10,000 RPM. Звучит как много. Один пользователь с automation-скриптом - 600 запросов в минуту. 17 таких пользователей - и весь аккаунт лежит. Но вот что интересно: проблема не в количестве запросов. Проблема в **токенах**.

Традиционный rate limiting считает запросы - 100 req/min, 1000 req/hour. Для LLM API это грубая метрика. Один запрос с 50,000 токенов контекста потребляет в 100 раз больше ресурсов, чем запрос с 500 токенами. Провайдеры вводят **TPM (tokens per minute)** - и именно он становится настоящим bottleneck. Rate limiting для AI - это не про 429 ошибки. Это про **token budget** по пользователям.

ПровайдерTierRPMTPMRPD
OpenAI (GPT-4o)Tier 150030,000-
OpenAI (GPT-4o)Tier 510,00030,000,000-
Anthropic (Claude Sonnet)Tier 15040,0001,000
Anthropic (Claude Sonnet)Tier 44,000400,000-
Google (Gemini 1.5)Free151,000,0001,500

Три слоя защиты в AI-приложении: 1. **защита от провайдера** - чтобы не получать 429 ошибки от OpenAI 2. **per-user квоты** - чтобы один пользователь не исчерпал лимит для всех 3. **budget protection** - финансовый потолок, выше которого не подниматься. Каждый слой решает свою задачу. Ни один нельзя пропустить.

**Retry - не замена rate limiting.** Retry спасает от спорадических 429, но при систематическом превышении лимита создаёт нарастающую очередь. 100 запросов → 70 429-ок → retry через 2 секунды → ещё 70 запросов → лимит исчерпан снова. Нужен proactive rate limiting до отправки запроса.

Почему стандартный rate limiting по количеству запросов (RPM) недостаточен для LLM API?

Token Bucket для LLM: ограничение по токенам, а не запросам

Token Bucket - алгоритм с историей. Ведро наполняется с постоянной скоростью. Каждый запрос берёт из ведра ровно столько, сколько стоит. Ведро пусто - запрос ждёт или уходит. Звучит просто, но есть нюанс: для LLM нужны **два ведра одновременно** - одно для RPM, другое для TPM. Первое защищает от storm of requests, второе - от одного запроса на 128K токенов.

Проблема: в момент отправки запроса количество **output токенов неизвестно** - модель ещё не начала генерацию. Стандартное решение - оценка: `system_tokens + user_tokens + max_tokens` (или среднее по истории запросов). После получения ответа `release()` возвращает неиспользованный кредит в ведро. Это сохраняет точность при систематически завышенных оценках.

Как token bucket обрабатывает ситуацию, когда фактическое потребление токенов оказалось меньше оценки?

Per-User Quotas с Redis: справедливое распределение ресурсов

Глобальный rate limit защищает от 429 провайдера. Но не от ситуации, когда один пользователь с automation-скриптом съедает 80% месячного бюджета за ночь. Per-user квоты - это **справедливость как архитектурное решение**. Лимит делится между пользователями, а не принадлежит тому, кто успел первым.

Redis - стандартный выбор для distributed rate limiting: атомарные операции, TTL на ключах, горизонтальное масштабирование. Ключи по userId + дата, сброс в полночь. Sliding window counter vs fixed window - для токенного бюджета достаточно fixed window: дневной лимит проще объяснить пользователю, чем скользящее окно.

Ответ при превышении квоты должен содержать **информативные заголовки**: `X-RateLimit-Remaining-Requests`, `X-RateLimit-Remaining-Tokens`, `X-RateLimit-Reset`. Стандарт де-факто - именно так делают OpenAI и GitHub API. Клиент получает точную информацию для graceful degradation вместо гадания по статус-коду.

Почему per-user quota использует adjustTokenUsage() после получения ответа от LLM?

NestJS Guard: rate limiting для AI endpoints

NestJS Guard - идеальное место для rate limiting: выполняется до controller, имеет доступ к request context, блокирует запрос до бизнес-логики. Guard для AI endpoints объединяет два слоя: global rate limit (защита от 429 провайдера) и per-user quota. Порядок важен - global идёт первым, иначе per-user пропустит запрос, который потом упадёт о лимит OpenAI.

В какой последовательности NestJS Guard проверяет rate limits?

Rate limiting для AI - это защита от DDoS и ботов

Rate limiting для AI - это в первую очередь управление token budget и стоимостью, а не защита от атак

DDoS-защита работает на уровне IP и количества запросов. Для LLM главная угроза другая: один легитимный пользователь с большим контекстом или automation-скриптом может потратить месячный бюджет за часы. Проблема не в злом умысле - проблема в том, что токены стоят денег, а их потребление непропорционально количеству запросов. Sliding window по RPM не спасает, когда один запрос = 50,000 токенов = 50 долларов.

Rate Limiting для AI API

  • LLM API ограничены по RPM и TPM. TPM - реальный bottleneck: один запрос с 50K токенов исчерпывает минутную квоту
  • Token Bucket с двумя измерениями: request bucket (RPM) + token bucket (TPM). release() возвращает неиспользованный кредит
  • Per-user quotas через Redis: дневные лимиты по запросам и токенам, разные тарифы (free/pro/enterprise), adjustTokenUsage() для точности
  • NestJS Guard: global rate limit → per-user quota → выполнение. Rate limit headers в каждом ответе

Что дальше

Rate limiting защищает от перерасхода и обеспечивает fair access. Следующая задача - понять, работает ли AI-система корректно, через evaluation и тестирование.

  • Evaluation: как тестировать LLM — Rate limiting - количественный контроль. Evaluation - качественный: правильно ли отвечает модель
  • Cost Management — Rate limiting и budget alerts - два механизма защиты бюджета, работающие в связке
  • Error Handling для LLM — 429 ошибки от rate limit - один из типов LLM-специфичных ошибок для graceful handling

Связанные уроки

  • aie-05-api-integration — Rate limiting оборачивает клиента провайдера
  • aie-29-cost-management — Лимиты защищают бюджет расходов
  • aie-32-error-handling-llm — Обрабатываем 429 через backoff и retry
  • aie-31-evaluation — Измеряем пропускную способность под давлением лимитов
  • net-62-rate-limiting — Тот же token-bucket на сетевом уровне
Rate Limiting для AI API: token bucket, sliding window, per-user quotas

0

1

Войти