Кошелёк перестаёт обновляться, приложение зависает на спиннере, а где-то за ним появляется сообщение о превышении лимита запросов. С вашими ключами, балансом и самой сетью всё в порядке. Оператор решил, что за отведённое окно вы задали больше вопросов, чем позволяет ваш тариф, и отклоняет всё, что приходит выше этой черты.
О чём на самом деле сообщает ошибка лимита
RPC-узел — это машина, которая отвечает на вопросы о сети за кошельки и приложения, не поднимающие собственный узел. Тот, кто эксплуатирует эту машину, решает и то, сколько вопросов вправе задать каждый вызывающий, и приводит решение в исполнение, отклоняя всё, что приходит выше потолка.
RFC 6585 даёт такому отказу отдельный код состояния. В нём сказано, что код 429 означает: пользователь отправил слишком много запросов за отведённое время, и сам раздел называет это состояние ограничением частоты; там же добавлено, что представления ответа SHOULD содержать пояснение условия и MAY включать заголовок Retry-After, указывающий, сколько ждать до нового запроса.
Отсюда два следствия, и оба легко упустить, глядя на сломанный экран. Отказ касается вызывающего, а не самого вызова: тот же самый запрос минутой раньше прошёл бы. А потолок — это политика одного оператора, а не свойство сети, поэтому другой эндпоинт с другой политикой ответит на тот же запрос без возражений.
Отказ приходит не в одном конверте
Не каждый ограниченный вызов возвращается кодом состояния HTTP. JSON-RPC 2.0 переносит ошибки внутри тела ответа, а его спецификация резервирует коды от -32000 до -32099 под серверные ошибки, определяемые реализацией, и именно там может оказаться сообщение провайдера об ограничении. Уровень HTTP при этом сообщает об обычном успехе.
| Где оказывается отказ | Как он выглядит | Почему его пропускают |
|---|---|---|
| Код состояния HTTP | Ответ 429, иногда с заголовком Retry-After | Незаметен клиенту, который проверяет только факт соединения |
| Тело JSON-RPC | Объект error с серверным кодом, определяемым реализацией | Статус HTTP успешный, поэтому проверка статуса пропускает его дальше |
| Формулировка клиента | Устаревший баланс, спиннер или общая сетевая ошибка | Формулировка написана для человека и не называет уровень, который отказал |
Поэтому диагностика начинается с того, какой из трёх случаев перед вами. Кошелёк, который говорит лишь о невозможности соединиться, не доказывает, что отказа не было: он доказывает, что кошелёк его не показал.
Лимиты не всегда считаются в запросах
Потолок, выраженный в вызовах в секунду, — лишь одна из форм лимита. Если оператор взвешивает вызовы, а не считает их, тяжёлый метод берёт из того же бюджета больше лёгкого, и бюджет расходуется быстрее, чем подсказывает число вызовов.
Поэтому «всего несколько вызовов» и «вы превысили лимит» могут одинаково точно описывать одну и ту же минуту. Запрос логов по широкому диапазону блоков — это один вызов по счёту и крупное списание по весу. Прочитать собственное описание оператора о том, что считает его бюджет, быстрее, чем ставить опыты.
Откуда на самом деле берётся объём запросов
Объём накапливается, а не выбирается. Он приходит из циклов, которые никто не считает циклами: экран, перечитывающий баланс по таймеру; компонент, заново запрашивающий данные при каждой перерисовке; фоновый наблюдатель, спрашивающий, попала ли транзакция в блок.
Арифметика здесь безжалостна, потому что интервал мал, а сессия длинна. Экран, обновляющий один баланс раз в секунду, за двенадцатичасовую сессию сам по себе порождает 43 200 вызовов, ещё до всяких действий пользователя. На фоне тарифа, разрешающего 100 000 вызовов в сутки, одна открытая вкладка уже забрала заметную долю дня.
Повторы — второй источник, и они умножают первый. Клиент, отвечающий на каждый отказ новой отправкой, превращает один превышенный потолок в поток отказов, причём именно тогда, когда оператор меньше всего готов его обслуживать.
Как повторять, не усугубляя отказ
Повторная отправка с тем же интервалом, который вызвал отказ, воспроизводит отказ. Правильная поправка — ждать после каждой неудачи дольше, а не столько же, чтобы интервал рос, а потолок оставался на месте, и останавливаться после ограниченного числа попыток, а не продолжать бесконечно.
Добавьте к ожиданию случайность. Клиенты, отклонённые в один и тот же момент и отступающие по одному и тому же правилу, вернутся тоже одновременно, и восстановление обернётся новым всплеском. Случайное смещение разносит ожидание и ломает эту синхронность, не стоя при этом ничего.
Если в ответе есть заголовок Retry-After, он заменяет догадку. Оператор сам назвал срок ожидания, и следовать этому значению быстрее придуманного вами расписания и с меньшей вероятностью зачтётся вам в минус.
Сокращать число запросов, а не поднимать потолок
Пакетирование — первое сокращение, и оно принадлежит протоколу, а не отдельному провайдеру. JSON-RPC 2.0 указывает, что для одновременной отправки нескольких объектов Request клиент MAY отправить массив, заполненный объектами Request, а сервер должен ответить массивом с соответствующими объектами Response после обработки всех объектов Request из пакета. Свернув десять вызовов в один массив, ту самую сессию из 43 200 вызовов вы превращаете в 4 320 запросов.
Кеширование — второе. Значения, которые не меняются между блоками, не нужно перечитывать между блоками: количество знаков токена, адрес контракта, квитанция уже завершённой транзакции. Всё окончательное кешируется бессрочно, и перечитывать его — чистый расход.
Подписки — третье, если эндпоинт их предлагает. Опрос снова и снова спрашивает, изменилось ли что-нибудь; подписка спрашивает один раз и получает уведомление, когда ответ меняется. Информация одна и та же, а бюджета они стоят очень по-разному.
| Что вы наблюдаете | Где на самом деле потолок | Что это меняет |
|---|---|---|
| Отказы при небольшой нагрузке | Взвешенный бюджет израсходован тяжёлыми методами | Сузить диапазоны блоков и разбить запрос |
| Отказы множатся после первого | Повторы бьются в тот же потолок | Отступать с растущим и рандомизированным ожиданием |
| Отказы от одной простаивающей вкладки | Цикл опроса по таймеру | Пакетировать, кешировать или подписываться вместо опроса |
| Отказы только в одной сети | Политика, привязанная к этому эндпоинту | Добавить второй эндпоинт для этой сети |
Когда повтор небезопасен
Чтения и записи повторяются по-разному. Спросить баланс дважды стоит одного лишнего вызова и ничего больше. Отправить подписанную транзакцию дважды — уже другое событие, а отказ на эндпоинте не говорит, по какую сторону этой границы транзакция остановилась.
Прежде чем отправлять снова, выясните, дошла ли первая попытка до мемпула. Транзакция, которую сеть уже держит, и новая транзакция с тем же намерением невзаимозаменяемы, и обращение с ними как с одной вещью — это и есть путь к двойной трансляции. В Solana точка отсчёта свежести делает тайминг наглядным: отправка, задержанная долгим отступлением, может упереться в истекший blockhash, и её придётся пересобирать, а не отправлять заново.
Та же осторожность касается и того, во что клиент поверит потом. Кошелёк, чьи чтения отклоняются, сверяет собственный счёт отправленных транзакций с представлением, которое он не смог обновить, и это один из путей к сообщению слишком высокий nonce. Счётчик не ошибается; не хватает картины, с которой его сравнили.
Смена эндпоинта чинит одну причину, а не остальные
Если потолок принадлежит оператору, переход к другому оператору переводит вас под другой потолок, и смена эндпоинта — обычный ремонт именно для этого случая. Сверьте chain ID новой записи, прежде чем что-либо через неё направлять, и сохраните запись, которая уже работала. Чего смена не достаёт, так это того, что сеть уже записала: транзакция, которая выполнилась и была откачена, помечается как reverted, и любой честный эндпоинт сообщает эту квитанцию одинаково.
Если объём принадлежит вам, переход покупает время и ничего больше. Тот же цикл опроса упрётся в потолок следующего оператора по тому же расписанию, а ротация между эндпоинтами ради пребывания под несколькими потолками сразу прячет цикл, а не чинит его.
Третий случай стоит отделить от обоих. Выделенный эндпоинт с вашим собственным ключом — это не просто больший лимит: он ещё и отделяет вас от других вызывающих, деливших общий публичный эндпоинт, поэтому полученный после этого отказ действительно ваш, и объяснять его вам.
Итог
Ошибка лимита говорит о том, сколько вы запросили, а не о том, имели ли вы право спрашивать. Она называет бюджет, окно и оператора, и полезный ответ начинается с того, какое из трёх сейчас связывает.
Читайте отказ на том уровне, где он оказался, соблюдайте Retry-After, когда он дан, и отступайте с растущим и рандомизированным ожиданием вместо отправки по старому расписанию. Затем сокращайте объём, а не гонитесь за большим потолком: пакетируйте то, что может ехать вместе, кешируйте то, что не меняется, и подписывайтесь вместо опроса. Вдвое больший лимит, съедаемый тем же циклом, кончится в тот же день. Чтобы продолжать изучать основы, следите за материалами Bitbase Academy.
Похожие материалы
Другие материалы Bitbase по этой теме:
- Как безопасно сменить RPC-эндпоинт
- Максимальная комиссия за транзакцию превышена: что означает это предупреждение кошелька
- Сид-фраза и пассфраза: разница и почему это важно
- Что такое финализация в блокчейне?
Дисклеймер: эта статья — образовательный материал Bitbase Academy, только для информационных целей. Она не является инвестиционным, торговым, налоговым или финансовым советом. Криптоактивы волатильны — оценивайте риски самостоятельно. Написано в сентябре 2026 года; сверяйтесь с актуальной официальной информацией.
Источники
[1] M. Nottingham, R. Fielding, Additional HTTP Status Codes, RFC 6585, IETF, апрель 2012 г. rfc-editor.org
[2] JSON-RPC 2.0 Specification, рабочая группа JSON-RPC, обновлено 4 января 2013 г. jsonrpc.org






