Ограничения частоты и квоты
Чем ограничение частоты отличается от квоты тарифа, какой код ответа приходит в каждом случае, есть ли заголовок ожидания и как правильно ждать и повторять запрос.
На этой странице
За кодом 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 не
несут, и это честно: ждать здесь нужно не секунды, и конец окна квоты
не приходится на предсказуемое смещение.
Как правильно ждать и повторять
- Прочитайте
error.code. Дальше поведение зависит только от него, а не от статуса. rate_limited— если естьRetry-After, ждите ровно столько. Если нет, считайте задержку сами: начните с одной секунды, удваивайте до потолка в 30 секунд, добавляйте случайное отклонение (jitter), ограничьте число попыток. Именно так ведёт себя браузерный SDK, и это разумный ориентир для серверного клиента.quota_exceededилиtrial_quota_exceeded— прекратите попытки, поднимите оповещение своей команде и буферизуйте события у себя. Повторы в цикле только тратят ваш же бюджет частоты.- Повторяйте последовательно, а не параллельно. Бюджет приёма привязан к префиксу ключа и общий для всех ваших процессов и реплик: десять клиентов, одновременно переспрашивающих одним ключом, продлевают отказ друг другу.
- Повторяйте так, чтобы повтор был безопасным. Для приёма это значит «тот же
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, а не пропускает трафик.
Порядок действий:
- Посмотрите потребление в кабинете: Настройки → Тариф и оплата. Там же видно состояние квоты — норма, предупреждение при достижении 100 % объёма и блокировка при 120 %. Те же данные доступны через методы раздела Billing.
- Решите, что делать с трафиком: сменить тариф или дождаться следующего периода. Оба варианта — действие человека, а не клиента.
- На стороне интеграции переключитесь в режим буферизации: складывайте события
у себя, сохраняя
event_id, и не повторяйте отправку в цикле. - После оплаты досылайте буфер порциями, помня про окно ±48 часов.
В пробном периоде лимит другой: не месячный объём, а суммарный кап за весь
триал (30 млн событий). При его исчерпании приём отвечает
trial_quota_exceeded; открывается он только оплатой тарифа. Запись сессий
считается отдельно и в объём событий не входит — она приостанавливается
жизненным циклом доступа, а не расходом квоты.
Всё описанное в этом разделе относится к облаку: тарифная квота и страница оплаты — его механика. В установке на своих серверах доступ определяется установленной лицензией, а не тарифом, — см. лицензию on-prem.
Что проверить в своём клиенте
- Клиент читает
error.code, а не только статус, и различаетrate_limitedиquota_exceeded. Retry-Afterучитывается, если пришёл, и есть своя задержка, если не пришёл.- У повторов есть потолок задержки, случайное отклонение и предел числа попыток.
- Повторы не идут параллельно одним ключом.
- Отказ по квоте поднимает оповещение вашей команде, а не превращается в бесконечный цикл.
- События на время отказа не выбрасываются, а буферизуются с сохранением
event_id. - Пакеты ограничены и по числу элементов, и по размеру тела.
Если 429 приходит там, где вы его не ждёте, начните с
кодов ошибок: статус один, а причин у него несколько.