Что ломается первым при игнорировании лимитов API
Компания, использующая три параллельные интеграции — ночную синхронизацию с ERP, веб-хук от платежной системы и внешнюю панель мониторинга, запрашивающую данные каждые пять минут, — не сталкивается с постепенным отказом систем. Она отлично работает до тех пор, пока не пересекает пороговое значение, после чего каждый последующий вызов API отклоняется с кодом REQUEST_LIMIT_EXCEEDED до ежедневного сброса. Отсутствует встроенное упреждающее предупреждение; есть лишь дашборд, на который можно посмотреть, если кто-то настроил процесс его проверки.
Этот тип сбоя отличается от большинства сбоев в проектах Salesforce тем, что он не зависит от некачественного кода или неудачной архитектуры. Он зависит от накопления: новая интеграция всегда строится с учетом текущего состояния, без проверки того, какая часть дневного бюджета уже израсходована существующими процессами. В результате, пятая интеграция «ломает» предыдущие четыре, хотя ни одна из них не изменилась.
Фактически актуальная карта лимитов
Не все существующие в Salesforce лимиты одинаково важны для планирования интеграций. Ниже представлены те, которые действительно определяют архитектуру:
| Тип лимита | Что измеряет | Кому вредит в первую очередь |
|---|---|---|
| Ежедневные запросы API | Общее количество вызовов REST/SOAP за 24 часа | Любая синхронная интеграция с высокой частотой выполнения |
| Пакеты Bulk API | Количество открытых/ежедневных пакетов | Ночные пакетные процессы, загружающие исторические данные |
| Параллельные длительные запросы | Одновременные запросы, выполняющиеся более 20 секунд | Тяжелые отчеты или сложный синхронный Apex |
| Доставка событий платформы | Объем событий в день на подписчика | Архитектуры Event-Driven между Salesforce и внешними системами |
| Строки SOQL на транзакцию | Количество строк, извлекаемых в одной транзакции (50 000) | Логика Apex, выполняющая запросы в цикле |
Эта таблица не является общим документом; это приоритизация. Организация, планирующая новую интеграцию, должна в первую очередь проверить первые две строки, поскольку именно они блокируются в производственной среде. Остальные лимиты влияют в основном на производительность, а не на доступность.
Бюджет вызовов: как правильно его построить
Основным инструментом предотвращения блокировок является не постфактум-мониторинг, а заранее определенный бюджет для каждого потребителя API. Принцип: каждая внешняя система, каждый интеграционный пользователь и каждый запланированный процесс получает определенное выделение из общего лимита, а не "сколько потребуется".
Построение бюджета включает три этапа:
- Картирование потребителей — список всех процессов, которые вызывают API: внешние интеграции, Scheduled Apex, ручной Data Loader, инструменты BI. Для каждого процесса выделяется отдельный Integration User для возможности изолированного отслеживания потребления в Event Monitoring.
- Расчет нагрузки на основе бизнес-объемов, а не допущений — сколько записей обрабатывается в день, сколько вызовов требуется для одной записи (включая извлечение Related Lists), и что происходит в пиковые периоды (конец квартала, Черная пятница, закрытие месяца).
- Выделение резерва — не следует распределять 100% лимита между существующими процессами. Оставьте 15–20% в качестве резерва для аварийных процессов, специальных отчетов и технического обслуживания – иначе любое небольшое дополнение подтолкнет организацию к превышению лимитов.
Тем, кто хочет углубиться в проектирование уровня, управляющего этим бюджетом на уровне платформы, рекомендуется ознакомиться с руководством по архитектуре CRM, где представлено разделение между интеграционным уровнем и бизнес-уровнем.
REST против Bulk: когда переход окупается
Наиболее распространенная ошибка — использование обычного REST API для высокообъемного обмена данными, поскольку именно он создается первым и работает в PoC. Проблема возникает, когда объем увеличивается: REST считает каждый запрос (до 200 записей в Composite) как отдельный вызов квоты, тогда как Bulk API 2.0 выполняет пакеты до 10 000 записей и учитывается со значительно меньшими затратами на каждую запись.
Практическое правило: если один процесс обновляет более 2000 записей за один проход, переход на Bulk API почти всегда оправдан — даже если это означает изменение кода потребителя для асинхронной работы с опросом статуса задачи вместо немедленного ответа. Ценой является более высокая задержка (минуты вместо секунд), поэтому Bulk не подходит для процессов, требующих принятия решений в реальном времени, таких как проверка наличия на складе перед подтверждением заказа.
Backoff и Retry: предотвращение самоутопления
Когда вызов API завершается сбоем из-за блокировки лимита, инстинктивная реакция большинства команд — немедленно повторить попытку. Именно такое поведение превращает временную блокировку в постоянный сбой: если десять процессов повторяют попытку в один и тот же момент, они заталкивают систему глубже в блокировку вместо того, чтобы дать ей восстановиться.
Правильный механизм Backoff требует трех компонентов:
- Экспоненциальное замедление (Exponential Backoff) — время ожидания между попытками растет экспоненциально (например, 2, 4, 8, 16 секунд), а не остается постоянным.
- Джиттер (Jitter) — небольшое случайное добавление к времени ожидания, чтобы параллельные процессы не повторяли попытку в одну и ту же секунду, создавая новую волну нагрузки.
- Автомат отключения (Circuit Breaker) — после нескольких последовательных сбоев (например, пяти) процесс полностью прекращает попытки на фиксированный период и отправляет уведомление в систему мониторинга, вместо того чтобы продолжать «стучаться в дверь».
Без Circuit Breaker процесс, который выполняется каждые пять минут и постоянно завершается сбоем, будет повторять попытки сто раз в день и расходовать квоту только на сбои — это прямо противоположно тому, что должен предотвращать механизм. Более подробная информация об обработке ошибок на уровне интеграции представлена в управлении ошибками интеграции в Salesforce.
Сценарий: розничная торговля с тремя точками интеграции
Предположим, средняя розничная сеть с 40 филиалами использует Salesforce Service Cloud в сочетании с системой POS и системой ERP для управления запасами. Действуют три активные интеграции: синхронизация запасов каждые 15 минут из ERP (около 8000 SKU), веб-хук из POS при каждой неудачной транзакции (около 300 в день) и внешняя панель мониторинга для Power BI, которая извлекает данные по обслуживанию каждый час.
В месяц, когда сеть внедрила новую программу лояльности, появилась четвертая интеграция: проверка бонусных баллов в реальном времени из Salesforce на каждой кассе, около 6000 дополнительных вызовов в день. Через две недели синхронизация запасов начала давать сбои около 14:00-15:00, в пиковые часы работы касс. Сначала команда проверила ERP и подумала, что проблема там, но лог Salesforce показал REQUEST_LIMIT_EXCEEDED именно в этот период.
Решение заключалось не в покупке дополнительной квоты, а в изменении приоритетов: проверка бонусных баллов была переведена на использование Platform Cache для часто не меняющихся результатов, что снизило количество вызовов примерно на 70%, а синхронизация запасов была переведена с REST на Bulk API с выполнением каждые 30 минут вместо 15. Результат: то же самое бизнес-покрытие, потребление квоты снизилось примерно на 45%, и появился реальный резерв для будущего роста.
Риски и конкретные профилактические меры
| Риск | Как проявляется на практике | Профилактическая мера |
|---|---|---|
| Новая интеграция не проверялась по существующему бюджету | Блокировка проявляется только после запуска в эксплуатацию | Требование обзора производительности (Capacity Review) для каждой новой интеграции до запуска |
| Повторная попытка без задержки | Временная блокировка становится проблемой на часы | Экспоненциальное замедление с джиттером и автоматом отключения у каждого потребителя API |
| Использование REST для больших объемов | Единичный процесс потребляет десятки процентов дневного лимита | Переход на Bulk API при превышении заданного порога объема |
| Отсутствие разделения интеграционных пользователей | Невозможно определить, какая интеграция потребляет квоту | Выделенный Integration User для каждой внешней системы, отслеживаемый отдельно |
| Отсутствие резерва в бюджете | Любое небольшое добавление приводит к превышению лимита | Выделение 15%-20% квоты в качестве постоянного резерва, не выделяемого для ежедневных процессов |
Чек-лист перед добавлением новой интеграции
- ☐ Известен текущий процент потребления дневной квоты по каждому Integration User.
- ☐ Проверен пиковый объем (не средний объем) новой интеграции.
- ☐ Принято решение между REST и Bulk API на основе порогового значения объема, а не удобства разработки.
- ☐ В коде потребителя присутствует механизм Backoff с Jitter и Circuit Breaker.
- ☐ Настроено оповещение, когда потребление дневной квоты превышает 70%.
- ☐ Проверена возможность использования Platform Cache для снижения повторных вызовов.
- ☐ Существует резерв в 15%-20% от квоты, не распределенный заранее.
- ☐ Определен операционный владелец, который получает оповещение, а не только технический лог.
Как это отслеживать на постоянной основе
Надежное измерение требует комбинации из трех источников: Event Monitoring (или Shield Event Monitoring) для фактического потребления API пользователем, Apex Limits в самом коде (Limits.getLimitApiRequests()) для локальной проверки во время выполнения, и встроенной панели мониторинга в разделе Company Information, которая отображает потребление относительно квоты на уровне организации. Ни один из этих источников не является достаточным сам по себе: первый показывает тенденцию, второй предотвращает отказ в рамках отдельного процесса, а третий служит ежедневной сводкой для операционной команды.
Показатель, который следует отслеживать в долгосрочной перспективе, — это не только «сколько было израсходовано», но и «каков ежемесячный темп роста потребления» — поскольку именно это позволяет предсказать, когда организация достигнет предела, вместо того чтобы реагировать после того, как блокировка уже произошла. Когда существует несколько взаимозависимых систем, стоит также рассмотреть общую модель интеграции с подключением Salesforce к системам ERP и вопрос реализации — Flow против Apex — что также влияет на эффективность вызовов, в Salesforce Flow или Apex.
Заключение
Лимиты Salesforce API — это не проблема, которую решают, когда она возникает, — это переменная, которая должна быть частью каждого интеграционного решения с самого первого дня. Документированный бюджет вызовов для каждого Integration User, осознанный выбор между REST и Bulk в зависимости от объема, а также механизм Backoff, который предотвращает самоутопление, — эти три элемента вместе отличают организацию, которая обнаруживает проблему только тогда, когда она уже заблокирована, от организации, которая видит ее приближение за месяц и действует своевременно.
