Заметки

Rate limit и ошибка 429: почему ИИ-API отказывает и как делать повторные попытки

M
Markabus
·
Тёмный рабочий стол разработчика крупным планом: монитор с плотным логом запросов, часть строк подсвечена красным, рядом график, упёршийся в потолок; вокруг — клавиатура, сетевой коммутатор с индикаторами и кабели в расфокусе

Вы отправляете запросы к API нейросети — OpenAI, Claude или Gemini — и в какой-то момент вместо ответа модели приходит 429 Too Many Requests. Ключ рабочий, деньги на счету есть, минуту назад всё работало. Это rate limit: ограничение на частоту обращений к API, которое провайдер выставляет каждому аккаунту. Разберёмся, в чём его измеряют, чем «кончились запросы в минуту» отличается от «кончились деньги», и как написать повторные попытки так, чтобы они помогали, а не добивали сервис.

Что такое rate limit и зачем он нужен

Rate limit — это потолок нагрузки, который API-провайдер разрешает одному аккаунту за единицу времени. Нужен он по трём причинам: защита от лавины (один клиент с кривым циклом не должен ронять сервис для остальных), справедливое распределение конечных GPU и предохранитель для вас самих — ошибка в коде, которая шлёт запросы в бесконечном цикле, упрётся в лимит и остановится, а не выставит счёт на месячный бюджет.

Важно не путать это с сетевым rate limiting на роутерах и балансировщиках — там речь про пакеты и полосу пропускания. Здесь всё про HTTP-запросы к API модели и про токены в них.

В чём измеряют лимит: RPM, TPM и остальные

Лимит почти никогда не один. Провайдеры считают сразу несколько метрик параллельно, и срабатывает та, которая исчерпается первой. Базовый набор такой:

  • RPM (requests per minute) — сколько HTTP-запросов в минуту вы можете отправить.
  • TPM (tokens per minute) — сколько токенов в минуту вы можете обработать. Токен — это кусочек текста примерно в 3–4 символа; подробнее о том, как их считать, есть отдельный разбор про токены и лимиты.
  • RPD / TPD (per day) — суточные потолки, типичны для бесплатных уровней.

Дальше начинаются различия.

OpenAI

Считает RPM, RPD, TPM, TPD, а для генерации картинок — IPM (images per minute); у аудиомоделей со стримингом отдельно тарифицируются минуты аудио. Лимиты привязаны к usage tier — уровню, который повышается автоматически по мере накопленных трат: первый порог открывается после пяти оплаченных долларов, дальше пороги растут до тысячи с лишним. Сам порядок уровней стабилен, конкретные цифры провайдер периодически меняет, так что сверяйтесь с документацией и страницей лимитов в своём кабинете.

Anthropic (Claude)

Здесь три метрики: RPM, ITPM (input tokens per minute) и OTPM (output tokens per minute) — входящие и исходящие токены считаются раздельно. Полезная деталь: для большинства моделей закэшированные входные токены в ITPM не засчитываются. То есть кэширование промптов у Claude экономит не только деньги, но и лимит — при большом неизменном системном промпте реальная пропускная способность вырастает в разы. Ещё одна особенность: лимит работает по алгоритму «дырявого ведра» (token bucket) — ёмкость восполняется непрерывно, а не обнуляется раз в минуту. Поэтому после 429 ждать полную минуту обычно не нужно.

Gemini

RPM, TPM и RPD, причём суточный счётчик сбрасывается в полночь по тихоокеанскому времени, а не по вашему. Уровни завязаны на траты и подключённый биллинг; отдельно есть ограничения по тратам в скользящем десятиминутном окне. При превышении приходит 429 RESOURCE_EXHAUSTED. Если у вас запросы к Gemini не проходят вообще, а не время от времени, проблема может быть не в лимите — смотрите разбор, почему не работает Gemini в России.

Общий обзор цен и потолков у трёх провайдеров собран в сравнении API Gemini, Claude и OpenAI.

Два разных 429: кончилась минута или кончились деньги

Это ключевая развилка, на которой ломается большинство самописных ретраев. Под одним и тем же кодом 429 скрываются две принципиально разные ситуации.

Первая — вы превысили частоту. Слишком много запросов или токенов в минуту. Это временно: подождали — и снова можно. Такой ответ повторять нужно и полезно.

Вторая — вы упёрлись в потолок расходов или исчерпали квоту. У OpenAI это отдельные коды вроде credit_balance_exhausted, organization_spend_limit_exceeded, project_spend_limit_exceeded. У Anthropic — rate_limit_error с деталью enforced_spend_limit_reached. Такой 429 повторять бессмысленно: сколько ни жди, доступ не вернётся, пока вы не пополните баланс или не поднимете лимит трат. Отличительный признак у Anthropic простой — в ответе про потолок расходов нет заголовка retry-after.

Отсюда правило: перед ретраем смотрите на тип ошибки. Биллинг и квота не ретраятся — они логируются и уходят в алерт человеку.

Рядом живёт ещё один сосед, который часто путают с 429: перегрузка на стороне провайдера. У OpenAI это 503 (server_is_overloaded), у Anthropic — нестандартный 529 (overloaded_error). Здесь вы ничего не превышали, просто сервису тяжело. Такие ответы, наоборот, нужно повторять с бэкоффом.

Заголовки ответа: как узнать, сколько осталось

Не обязательно ждать отказа, чтобы понять, что вы близко к потолку. Провайдеры отдают счётчики в заголовках каждого успешного ответа.

OpenAI присылает пары «лимит / остаток / сброс» отдельно по запросам и по токенам: x-ratelimit-limit-requests, x-ratelimit-remaining-requests, x-ratelimit-reset-requests и аналогичные *-tokens. Anthropic — три группы с префиксом anthropic-ratelimit-: requests-*, input-tokens-* и output-tokens-*, тоже в трёх вариантах (limit, remaining, reset).

Практический приём: логируйте remaining из каждого ответа и стройте по нему график. Тогда вы увидите, что упираетесь в TPM, за несколько дней до того, как 429 начнёт валиться в продакшене — это та же логика, что в заметке про мониторинг ошибок PHP на проде.

Retry-After и экспоненциальный бэкофф с джиттером

Код 429 определён в RFC 6585, и вместе с ним сервер может прислать заголовок Retry-After — либо целое число секунд, либо дату в формате HTTP. Это прямое указание: раньше не приходи. Если заголовок есть, его значение — нижняя граница паузы, а не рекомендация, которую можно округлить в меньшую сторону.

Если Retry-After нет, работает экспоненциальный бэкофф: после каждой неудачи пауза удваивается — 1, 2, 4, 8 секунд. И обязательно с джиттером (случайной добавкой). Без него все клиенты, отказавшие в одну и ту же секунду, синхронно вернутся ровно через секунду и положат сервис снова — это называется «эффект громового стада» (thundering herd).

import random, time
from anthropic import RateLimitError

def call_with_retry(client, max_attempts=6, **kwargs):
    for attempt in range(max_attempts):
        try:
            return client.messages.create(**kwargs)
        except RateLimitError as e:
            hdr = e.response.headers
            # потолок расходов: retry-after не придёт, повторять бесполезно
            if "retry-after" not in hdr:
                raise
            base = float(hdr["retry-after"])
            delay = max(base, 2 ** attempt) + random.uniform(0, 1)
            time.sleep(delay)
    raise RuntimeError("Лимит не отпустил за отведённые попытки")

Три вещи, которые легко упустить:

  1. Ограничьте число попыток и общее время ожидания. Бесконечный ретрай превращает деградацию в зависание: пользователь смотрит на крутилку десять минут вместо честного сообщения об ошибке.
  2. Не вкладывайте ретраи друг в друга. Официальные SDK и OpenAI, и Anthropic уже повторяют подходящие 429 и 5xx с бэкоффом сами (у Anthropic по умолчанию две попытки). Если вы оборачиваете это своим циклом, попытки перемножаются: шесть ваших на две SDK-шных дают двенадцать реальных обращений. Либо отключите встроенные ретраи параметром вроде max_retries=0, либо не пишите свои.
  3. Разгоняйтесь постепенно. Резкий скачок трафика с нуля до потолка ловит отдельную ошибку ускорения (slow_down у OpenAI). Если запускаете массовую обработку, наращивайте параллелизм плавно.

Как вообще не упираться в лимит

Ретраи — это лечение симптома. Гораздо надёжнее выстроить работу так, чтобы 429 приходил редко.

Ограничьте параллелизм у себя. Самая частая причина 429 — не объём работы, а её форма: код запускает сто задач разом вместо того, чтобы держать, скажем, пять одновременных запросов. Семафор или очередь с фиксированным числом воркеров решают проблему целиком.

Считайте токены заранее. Если известен размер промпта, можно не отправлять запрос, который гарантированно пробьёт TPM, а придержать его на пару секунд. Это дешевле, чем получить отказ и ждать.

Используйте кэширование промптов. У Claude кэшированный вход не тратит ITPM — самый прямой способ поднять потолок без смены тарифа.

Переносите неспешное в Batch API. Пакетная обработка живёт на отдельной квоте и не трогает ваши обычные лимиты, стоит вдвое дешевле и выполняется в окне до 24 часов. Для переиндексации базы, классификации архива или прогонки тестовых наборов это правильный инструмент.

Повышайте уровень. Уровни поднимаются автоматически по накопленным тратам, но у всех трёх провайдеров есть форма запроса повышенного лимита вручную — если у вас прогнозируемая нагрузка, её стоит заполнить заранее, а не в день запуска.

И отдельно: стриминг ответов лимит не экономит. Он улучшает ощущение скорости для пользователя, но токены расходуются ровно те же.

Чек-лист

  • Различать 429 по частоте и 429 по деньгам; вторые не ретраить.
  • Уважать Retry-After, если он пришёл.
  • Экспоненциальный бэкофф обязательно с джиттером.
  • Ограничить число попыток и суммарное время ожидания.
  • Не дублировать ретраи SDK своими.
  • Логировать remaining из заголовков и мониторить приближение к потолку.
  • Ограничить параллелизм на своей стороне.
  • Спокойные задачи — в Batch, повторяющийся контекст — в кэш.

Вывод

Ошибка 429 — не поломка, а штатный сигнал от API: «сбавь темп». Проблемы начинаются там, где на неё реагируют одинаково во всех случаях — слепым циклом повторов без пауз. Разделите временные отказы и упёршуюся квоту, дождитесь того, что просит Retry-After, добавьте джиттер и потолок попыток — и rate limit превратится из источника аварий в фоновое ограничение. А начинать стоит с заголовков: они говорят, что лимит близко, задолго до первого отказа.

Частые вопросы

Q.Сколько ждать после ошибки 429?

Если в ответе есть заголовок Retry-After — ровно столько секунд, сколько в нём указано, плюс небольшая случайная добавка. Если заголовка нет, начните с 1–2 секунд и удваивайте паузу после каждой неудачи, ограничив общее число попыток пятью-шестью. Ждать целую минуту обычно не нужно: у Anthropic, например, ёмкость лимита восполняется непрерывно.

Q.Чем 429 отличается от 503 и 529?

429 означает, что лимит превысили вы. 503 у OpenAI и 529 у Anthropic означают, что перегружен сам провайдер, и вы тут ни при чём. Реакция в обоих случаях похожа — повторить с экспоненциальным бэкоффом, — но различать их полезно: всплеск 429 лечится вашим кодом и тарифом, всплеск 529 — только ожиданием.

Q.Почему повторные попытки не помогают и 429 продолжает приходить?

Скорее всего, это не лимит частоты, а потолок расходов или исчерпанная квота: у OpenAI это коды вида credit_balance_exhausted и organization_spend_limit_exceeded, у Anthropic — деталь enforced_spend_limit_reached, причём заголовок retry-after в таком ответе не приходит. Такой отказ не лечится ожиданием — нужно пополнить баланс или поднять лимит трат в кабинете.

Q.Считаются ли закэшированные токены в лимит?

У Anthropic для большинства моделей закэшированные входные токены не засчитываются в ITPM, поэтому кэширование промптов заметно поднимает реальную пропускную способность. У других провайдеров правила отличаются, и это стоит проверять в их документации отдельно.

Источники

Предыдущая
Cursor AI: настройка и первые шаги
Следующая
Промпт для текста: как получить от нейросети статью, а не воду

Читайте также

Рабочий стол в полумраке: монитор с черновиком статьи в текстовом редакторе, рядом распечатка с правками красной ручкой и блокнот с планомЗаметки
18 сентября 2026 г.

Промпт для текста: как получить от нейросети статью, а не воду

Короткий запрос «напиши статью про X» всегда даёт одно и то же — общие слова и списки без цифр. Разбираем, почему так происходит, и собираем каркас промпта из шести блоков, который даёт текст, готовый к вычитке.

Читать →
Крупный план ноутбука на тёмном рабочем столе: на экране редактор кода с подсвеченным синтаксисом и боковая панель ИИ-агента с диффом правок, рядом в расфокусе терминал, механическая клавиатура и внешний SSDЗаметки
15 сентября 2026 г.

Cursor AI: настройка и первые шаги

Практический гайд по Cursor: установка и перенос настроек из VS Code, четыре режима работы, выбор модели, правила проекта в .cursor/rules и AGENTS.md, .cursorignore, подключение MCP и актуальные тарифы.

Читать →
Монитор на рабочем столе в тёмной комнате: на экране схема автоматизации из связанных узлов, рядом второй экран с терминалом, клавиатура и кабелиЗаметки
14 сентября 2026 г.

n8n и нейросети: автоматизация без кода

n8n — визуальный конструктор сценариев, в котором нейросеть становится обычным блоком на холсте. Разбираем, как запустить n8n в облаке и на своём сервере, из чего собирается ИИ-узел, как подключить внешние инструменты через MCP и во что это обходится.

Читать →