К содержанию
ActionPulse

Ограничения частоты и квоты

Чем ограничение частоты отличается от квоты тарифа, какой код ответа приходит в каждом случае, есть ли заголовок ожидания и как правильно ждать и повторять запрос.

Кому
Разработчикам, обращающимся к API часто или большими объёмами
Проверено
На этой странице

За кодом 429 стоят два совершенно разных события: вы обратились слишком часто или вы израсходовали объём, оплаченный тарифом. Первое проходит через секунды само, второе не пройдёт никогда, сколько бы вы ни повторяли. Различать их нужно по коду в теле ответа — статус у них общий.

Частота и квота — это разные ограничения

Ответ 429 в контракте описан одной формулировкой сразу для обоих случаев: ограничение частоты — это rate_limited, исчерпание квоты тарифа — quota_exceeded. Отдельно оговорено поведение пробного периода: если живой триал израсходовал свой суммарный лимит событий, на операциях приёма вместо quota_exceeded приходит trial_quota_exceeded.

Код в теле Статус Что произошло Помогает ли ожидание
rate_limited 429 слишком много запросов или слишком большой объём за короткое окно да, секунды
quota_exceeded 429 израсходован месячный объём событий тарифа нет, до следующего периода или смены тарифа
trial_quota_exceeded 429 израсходован суммарный лимит событий пробного периода нет, до оплаты тарифа
subscription_required 402 нет действующей подписки и нет живого триала нет, до выбора тарифа
trial_expired 402 триал закончился без оплаты нет, до оплаты
trial_pending_review 403 аккаунт на проверке, приём приостановлен да, но не минутами

Разница принципиальная и для кода, и для дежурного: rate_limited — это нормальная обратная связь работающей интеграции, её нужно переждать. Всё остальное в таблице означает, что приём или запись приостановлены и данные теряются до действия человека. В ответах 402 может присутствовать details.billing_url — адрес страницы оплаты в кабинете.

Заголовок ожидания

Каждый отказ по частоте (rate_limited) приходит с заголовком Retry-After в секундах — так отвечают и приём событий, и методы приложения. Обычно это время до конца текущего окна лимитера, у части маршрутов — фиксированное значение; меньше 1 он не приходит. На отметках релиза то же число дополнительно приходит в details.retry_after_seconds.

Заголовков семейства RateLimit-* или X-RateLimit-* в продукте нет вообще — узнать остаток бюджета заранее нельзя, счётчика вам никто не отдаёт.

Отказы по квоте (quota_exceeded, trial_quota_exceeded) Retry-After не несут, и это честно: ждать здесь нужно не секунды, и конец окна квоты не приходится на предсказуемое смещение.

Как правильно ждать и повторять

  1. Прочитайте error.code. Дальше поведение зависит только от него, а не от статуса.
  2. rate_limited — если есть Retry-After, ждите ровно столько. Если нет, считайте задержку сами: начните с одной секунды, удваивайте до потолка в 30 секунд, добавляйте случайное отклонение (jitter), ограничьте число попыток. Именно так ведёт себя браузерный SDK, и это разумный ориентир для серверного клиента.
  3. quota_exceeded или trial_quota_exceeded — прекратите попытки, поднимите оповещение своей команде и буферизуйте события у себя. Повторы в цикле только тратят ваш же бюджет частоты.
  4. Повторяйте последовательно, а не параллельно. Бюджет приёма привязан к префиксу ключа и общий для всех ваших процессов и реплик: десять клиентов, одновременно переспрашивающих одним ключом, продлевают отказ друг другу.
  5. Повторяйте так, чтобы повтор был безопасным. Для приёма это значит «тот же event_id» — см. идемпотентность и повторы.

Сколько именно можно

Числовые пороги частоты ActionPulse не публикует: они зависят от установки и от нагрузки, и клиент, построенный на конкретном числе, ломается при первом же изменении конфигурации. Правильное поведение — читать ответ, а не угадывать порог.

Исключение — несколько операций, у которых лимит объявлен прямо в контракте:

Операция Объявленный лимит
Повторная отправка кода подтверждения регистрации 1 запрос в минуту на адрес электронной почты плюс общий лимит на IP
Запуск SMS-активации пробного периода 3 запуска в час на организацию и на телефон
Экспорт результата отчёта в CSV 10 запусков в минуту на организацию, 2 активных экспорта на организацию
Экспорт сырых событий те же 10 запусков в минуту и 2 одновременных потока на организацию, не более 1 000 000 записей и 30 секунд
Предпросмотр сезонного оповещения 10 запросов в минуту на организацию
Открытие защищённой ссылки лимит по адресу источника и отпечатку токена, значение не публикуется
Живой поток событий выше 20 сообщений в секунду поток прореживается

Как считается стоимость запроса на приёме

Бюджет приёма измеряется не в запросах, а в единицах работы за секунду на префикс ключа. Стоимость одного запроса — это большее из двух: число событий в пакете и размер тела в килобайтах. Пакет из 500 небольших событий стоит 500 единиц; пакет из 10 «толстых» событий на 200 КБ — 200 единиц; один маленький запрос — одну.

Практический вывод: пакетирование экономит запросы, а не бюджет. Число событий в секунду — это и есть ваш основной расход, и уложить их в меньшее число запросов стоимость не снижает. Зато очень крупные тела дорожают отдельно, так что имеет смысл держать свойства события компактными. В собственной установке бюджет задаётся переменной INGEST_RATE_LIMIT_RPS (значение по умолчанию — 1000 единиц в секунду).

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

Ограничения объёма запроса

Слишком большое тело — это 413, и в конверте у него не отдельный код, а validation_failed. Превышение числа элементов в пакете — 422.

Что ограничено Значение Ответ
Тело запроса приёма событий 256 КБ 413
Элементов в одном пакете 500 422
Тело связывания личности (/v1/identify, /v1/alias) 64 КБ 413
Тело чанка записи сессии (/v1/replay) 800 КиБ 413
Тело захвата элемента (/v1/picker/capture) 8 КиБ 413

У остальных методов байтовый лимит существует, но в контракте не назван — поэтому не проектируйте запрос «под предел», а разбивайте его на страницы и пакеты. Для чтения предел жёсткий и объявлен у каждого метода: на большинстве постраничных методов limit не превышает 100 записей, у отдельных предел свой. Забрать всё одним запросом нельзя — нужен курсор, см. постраничность.

Что делать при исчерпании квоты

Квота — это месячный объём событий тарифа. Когда он израсходован, приём отвечает 429 quota_exceeded с сообщением о том, что нужно сменить тариф или дождаться следующего периода. Проверка идёт по метке состояния, и она намеренно закрывается «в минус»: незнакомое значение метки тоже даёт quota_exceeded, а не пропускает трафик.

Порядок действий:

  1. Посмотрите потребление в кабинете: Настройки → Тариф и оплата. Там же видно состояние квоты — норма, предупреждение при достижении 100 % объёма и блокировка при 120 %. Те же данные доступны через методы раздела Billing.
  2. Решите, что делать с трафиком: сменить тариф или дождаться следующего периода. Оба варианта — действие человека, а не клиента.
  3. На стороне интеграции переключитесь в режим буферизации: складывайте события у себя, сохраняя event_id, и не повторяйте отправку в цикле.
  4. После оплаты досылайте буфер порциями, помня про окно ±48 часов.

В пробном периоде лимит другой: не месячный объём, а суммарный кап за весь триал (30 млн событий). При его исчерпании приём отвечает trial_quota_exceeded; открывается он только оплатой тарифа. Запись сессий считается отдельно и в объём событий не входит — она приостанавливается жизненным циклом доступа, а не расходом квоты.

Всё описанное в этом разделе относится к облаку: тарифная квота и страница оплаты — его механика. В установке на своих серверах доступ определяется установленной лицензией, а не тарифом, — см. лицензию on-prem.

Что проверить в своём клиенте

  • Клиент читает error.code, а не только статус, и различает rate_limited и quota_exceeded.
  • Retry-After учитывается, если пришёл, и есть своя задержка, если не пришёл.
  • У повторов есть потолок задержки, случайное отклонение и предел числа попыток.
  • Повторы не идут параллельно одним ключом.
  • Отказ по квоте поднимает оповещение вашей команде, а не превращается в бесконечный цикл.
  • События на время отказа не выбрасываются, а буферизуются с сохранением event_id.
  • Пакеты ограничены и по числу элементов, и по размеру тела.

Если 429 приходит там, где вы его не ждёте, начните с кодов ошибок: статус один, а причин у него несколько.