12 окт. 2025 г.·8 мин

Ограничение частоты запросов для публичных API: практические квоты и сценарии блокировок

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

Ограничение частоты запросов для публичных API: практические квоты и сценарии блокировок

Какая проблема решается ограничением частоты запросов

Ограничение частоты запросов для публичных API — это не наказание пользователей. Это предохранительный клапан, который сохраняет доступность сервиса, когда трафик ведёт себя странно — будь то злонамеренная активность или просто ошибка клиента.

«Злоупотребления» часто сначала выглядят как нормальный трафик: скрейпер проходит по всем эндпойнтам, чтобы скопировать данные, перебор логинов, «token stuffing» на маршрутах авторизации или клиент, зациклившийся и повторяющий один и тот же запрос в коротком цикле. Иногда атаки вообще нет — обновление мобильного приложения выходит с неверным правилом кэширования, и все устройства начинают опрашивать API каждую секунду.

Задача простая: защищать аптайм и контролировать расходы, не блокируя реальных пользователей, которые работают как обычно. Если ваш бэкенд тарифицируется (компьютинг, база данных, email/SMS, вызовы AI), один шумный актор может быстро превратиться в большую счёт‑фактуру.

Одного лимитера запросов недостаточно. Без мониторинга и понятных ответов вы получите тихие отказы, растерянных клиентов и тикеты в поддержку с «ваш API упал», когда на самом деле идёт троттлинг.

Полная защита обычно состоит из нескольких отдельных частей:

  • Лимиты запросов: капы в коротких окнах (в секунду/минуту), которые останавливают всплески.
  • Квоты: бюджеты в более длинных окнах (в день/месяц), которые делают использование предсказуемым.
  • Блокировки: временные баны по очевидным признакам злоупотребления.
  • Исключения: allowlist для доверенных интеграций, внутренних инструментов или VIP‑клиентов.

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

Ключевые термины: лимиты, квоты, троттлинг и блокировки

Эти термины часто смешивают, но они решают разные задачи и ощущаются по‑разному для пользователей.

Что означает лимит, квота и конкурентность

Лимит (rate limit) — это ограничение скорости: сколько запросов клиент может делать в коротком окне (в секунду, в минуту). Квота — это бюджет: суммарное использование за более длинный период (в день, в месяц). Ограничение конкурентности (concurrency limit) лимитирует, сколько запросов может выполняться одновременно — полезно для дорогих эндпойнтов, даже если скорость запросов в целом выглядит нормальной.

Где вы прикрепляете ограничение, имеет значение:

  • По IP: просто, но наказывается общий доступ (офисы, школы, мобильные операторы).
  • По пользователю: отлично для авторизованных приложений, но зависит от надёжной идентификации.
  • По API‑ключу: распространено для публичных API — простая ответственность и удобство объяснения.
  • По эндпойнту: полезно, когда какой‑то маршрут значительно дороже других.

Троттлинг против блокировки и где уместны lockout'ы

Мягкий троттлинг замедляет клиента (задержки, уменьшение буста), чтобы он восстановился без слома рабочих процессов. Жёсткая блокировка немедленно отклоняет запросы, обычно возвращая HTTP 429.

Lockout сильнее обычного 429. 429 говорит «попробуйте позже». Lockout говорит «остановитесь, пока не выполнится условие»: период остывания, ручная проверка или сброс ключа. Резервируйте блокировки для ясных сигналов злоупотреблений (перебор учётных данных, агрессивный скрейпинг, повторные неверные авторизации), а не для обычных всплесков трафика.

Если вы строите API с помощью AppMaster, рассматривайте эти механизмы отдельно: короткие лимиты для поглощения всплесков, более длинные квоты для контроля затрат и блокировки только при повторяющемся плохом поведении.

Как выбрать практичные лимиты без гаданий

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

Простой старт — лимит по API‑ключу, соответствующий типу вашего API:

  • Низкий трафик: 60–300 запросов в минуту на ключ
  • Средний трафик: 600–1500 запросов в минуту на ключ
  • Высокий трафик: 3000–10000 запросов в минуту на ключ

Затем разделите лимиты по типу эндпойнтов. Чтения обычно дешевле и могут иметь более высокие лимиты. Записи меняют данные, часто запускают дополнительную логику и заслуживают более жёстких капов. Обычный паттерн: ~1000/мин для GET‑маршрутов и 100–300/мин для POST/PUT/DELETE.

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

Планируйте всплески с двумя окнами: короткое для быстрых шипов и длинное для длительного контроля. Частая комбинация — 10 секунд плюс 10 минут. Это помогает реальным пользователям, которые кликают быстро, но не даёт скрейперам безграничной скорости.

Наконец, решите, что происходит при превышении лимита. Большинство публичных API возвращают HTTP 429 с понятным временем повтора. Если задача безопасно откладывается (например, экспорт), рассмотрите очередь вместо жёсткой блокировки, чтобы реальные пользователи всё равно получали результат позже.

Проектирование квот по ключу, которые кажутся честными

Квоты по ключу обычно честнее всего, потому что соответствуют реальному использованию: один аккаунт — один API‑ключ, понятная ответственность. Ограничение по IP всё ещё полезно, но часто переносит наказание на невиновных.

Общие IP — главная причина. Целый офис может выходить через один публичный IP, мобильные операторы могут ставить тысячи устройств за небольшим пулом IP. Если вы опираетесь на лимиты по IP, один шумный пользователь может замедлить всех остальных. Квота по ключу этого избегает; небольшой per‑IP лимит можно оставить как подстраховку для очевидных флудов.

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

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

  • Разрешайте короткие всплески (загрузка страниц, импорт), затем поддерживайте стабильную скорость.
  • Добавьте дневной лимит на ключ, чтобы ограничить скрейпинг и бесконечные циклы.
  • Увеличивайте лимиты по плану, но сохраняйте ту же структуру — чтобы поведение оставалось постоянным.
  • Для новых ключей ставьте более низкий кап, пока не накопится положительная история.
  • Держите небольшой per‑IP лимит, чтобы ловить очевидные флуды и неправильно настроенных клиентов.

Чтобы отпугнуть шаринг ключей и автоматические регистрации, не нужна слежка. Начните с простых проверок: необычные геоперемещения, слишком много разных IP за час для одного ключа или много новых ключей с одного источника. Сначала пометьте и замедлите; блокируйте только после повторных сигналов.

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

Если вы строите API в AppMaster, логика по ключу проще держать согласованной, потому что аутентификация, бизнес‑правила и обработка ответов живут в одном месте.

Клиент‑дружелюбные ответы и заголовки (чтобы пользователи могли восстановиться)

Дизайн эндпойнтов по реальной стоимости
Моделируйте данные в PostgreSQL и контролируйте дорогие эндпойнты с первого дня.
Начать разработку

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

Когда клиент попадает в лимит, возвращайте HTTP 429 (Too Many Requests) с понятным сообщением и конкретным временем ожидания. Самый быстрый выигрыш — добавить Retry-After, потому что даже простые клиенты смогут корректно паузить.

Небольшой набор заголовков делает лимиты самодокументируемыми. Держите имена согласованными и включайте их как в успешные ответы (чтобы клиенты могли регулировать скорость), так и в 429‑ответы (чтобы клиенты восстанавливались):

  • Retry-After: сколько секунд ждать перед повтором
  • X-RateLimit-Limit: текущий разрешённый объём запросов в окне
  • X-RateLimit-Remaining: сколько осталось в текущем окне
  • X-RateLimit-Reset: когда окно сбросится (в секундах epoch или ISO‑времени)
  • X-RateLimit-Policy: краткий текст, например "60 requests per 60s"

Делайте тело ошибки структурированным, как успешные ответы. Частый паттерн — объект ошибки с постоянным code, удобочитаемым message и подсказками по восстановлению.

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please retry after 12 seconds.",
    "retry_after_seconds": 12,
    "limit": 60,
    "remaining": 0,
    "reset_at": "2026-01-25T12:34:56Z"
  }
}

Объясните клиентам, как отступать при 429. Экспоненциальный бэкофф — хороший дефолт: 1s, затем 2s, затем 4s, с капом, например 30–60 секунд. Также укажите, когда прекращать повторы.

Избегайте сюрпризов около квот. Когда ключ близок к капу (80–90% использования), добавляйте предупреждение в поле или заголовок, чтобы клиенты замедлились до начала сбоев. Это особенно важно, когда один скрипт может быстро пройти по нескольким маршрутам и сжечь бюджет быстрее, чем ожидается.

Пошаговый план развёртывания лимитов и квот

Реализуйте квоты без кастомного кода
Используйте визуальные бизнес‑процессы для подсчёта запросов, применения квот и возвращения понятных 429 ответов.
Создать бэкенд

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

Начните с инвентаризации: перечислите все эндпойнты и пометьте каждый по стоимости (CPU, работа с БД, сторонние вызовы) и риску (логин, сброс пароля, поиск, загрузка файлов). Так вы не примените одно жёсткое правило ко всему.

Порядок развёртывания, который обычно избегает сюрпризов:

  • Пометьте эндпойнты по стоимости и риску; решите, какие требуют более строгих правил (логин, массовый экспорт).
  • Выберите идентификационные ключи в приоритетном порядке: сначала API‑ключ, затем user id, и только потом IP как запасной вариант.
  • Добавьте короткоокружные лимиты (например, на 10 секунд или на минуту), чтобы остановить всплески и скрипты.
  • Добавьте длиннее окна‑квоты (в час или в день), чтобы ограничить устойчивое использование.
  • Добавьте allowlist для доверенных систем и внутренних инструментов, чтобы операционная работа не блокировалась.

Сделайте первый релиз консервативным — легче ослабить позже, чем разблокировать разгневанных пользователей.

Мониторьте и настраивайте, затем версионируйте политику. Отслеживайте, сколько запросов попадает под лимиты, какие эндпойнты их триггерят и сколько уникальных ключей затронуто. При изменении чисел трактуйте это как изменение API: документируйте, выкатывайте поэтапно и держите старые и новые правила отдельно, чтобы быстро откатиться.

Если вы строите API с AppMaster, планируйте эти правила вместе с эндпойнтами и бизнес‑логикой, чтобы лимиты соответствовали реальной стоимости каждого рабочего процесса.

Сценарии блокировок, которые останавливают злоупотребления без драмы

Блокировки — это ремень безопасности. Они должны быстро останавливать явное злоупотребление, но давать нормальным пользователям понятный путь восстановления.

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

Простая прогрессивная лестница

Используйте небольшой набор шагов, которые легко объяснить и реализовать:

  • Предупреждение: скажите клиенту, что он приближается к лимитам, и укажите время сброса.
  • Замедление: добавьте короткие задержки или ужесточьте лимит в секунду для этого ключа.
  • Временная блокировка: блок на минуты (не часы) с точным временем разблокировки.
  • Длинная блокировка: только после повторных всплесков в разных окнах.
  • Ручная проверка: для паттернов, которые выглядят целенаправленно или повторяются.

Важно, что блокировать лучше по API‑ключу: это точнее — таргетирует вызывающего, а не всех за общим IP. Блокировка по аккаунту полезна, когда пользователи регулярно ротируют ключи. Блокировка по IP помогает для анонимного трафика, но даёт ложные срабатывания для NAT, офисов и мобильных операторов. При серьёзном злоупотреблении комбинируйте сигналы (например, заблокируйте ключ и потребуйте дополнительные проверки для этого IP), но держите радиус поражения небольшим.

Делайте блокировки на время с простыми правилами: «заблокировано до 14:05 UTC» и «сброс после 30 минут нормального поведения». Избегайте вечных банов для автоматизированных систем — багнутый клиент может быстро пройти цикл и сжечь лимиты. Наказывайте постепенно; при устойчивом спокойном трафике уровень штрафа должен уменьшаться.

Если вы строите API в AppMaster, эту лестницу просто реализовать через счётчики и бизнес‑процесс, который решает allow/slow/block и записывает время разблокировки для ключа.

Для повторных нарушителей держите путь ручной проверки. Не вступайте в споры с пользователями: запросите ID запросов, таймстемпы и имя API‑ключа, а затем принимайте решение на основании фактов.

Распрострённые ошибки, ведущие к ложным срабатываниям

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

Ложные срабатывания — когда защита блокирует нормальных пользователей. Обычно это происходит, когда правила слишком просты для реального использования API.

Классическая ошибка — один глобальный лимит для всего. Если вы одинаково обрабатываете дешёвые read‑эндпойнты и дорогие экспорты, то либо вы чрезмерно защищаете дешёвые маршруты (раздражая клиентов), либо недоохраняете дорогие (риск для инфраструктуры). Разделяйте лимиты по стоимости эндпойнта и ужесточайте для тяжёлых путей.

Лимитирование только по IP — ещё одна ловушка. Множество реальных пользователей могут делить один публичный IP (офисы, школы, мобильные сети). Один тяжёлый пользователь может заблокировать всех, и это выглядит как случайные отключения. Сначала ограничивайте по API‑ключу, IP используйте как дополнительный сигнал.

Отказы системы лимитирования тоже дают ложные срабатывания. Если стор лимитера упал, «fail closed» может вывести весь API из строя. «Fail open» может впустить всплеск, который всё равно упадёт бэкенд. Выберите понятный fallback: небольшой аварийный кап на краю и плавное деградирование некритичных эндпойнтов.

Обработка на клиенте важнее, чем многие команды ожидают. Если вы возвращаете общий 429 без понятного сообщения, пользователи будут ретраить чаще и усугублять проблему. Всегда отправляйте Retry-After и конкретный текст ошибки (например, "Too many requests for this key. Try again in 30 seconds.").

Самая избегаемая проблема — секретность. Скрытые лимиты кажутся багом, когда клиенты впервые выходят в прод. Делитесь простой политикой и удерживайте её стабильной.

Короткая проверочная таблица против ложных срабатываний:

  • Разделение лимитов для дорогих и дешёвых эндпойнтов
  • Основное ограничение по API‑ключу, не только по IP
  • Определённое поведение при недоступности лимитера
  • Понятные 429 с Retry-After
  • Документированные лимиты и коммуникация до включения

Если вы используете AppMaster, это обычно значит настройку разных капов на эндпойнт и возврат согласованного payload ошибки, чтобы клиенты могли корректно отступать.

Мониторинг и алертинг, которые действительно помогают

Ограничения работают только если вы видите, что происходит в реальном времени. Цель — не поймать каждый всплеск, а заметить паттерны, которые приводят к падениям или недовольству клиентов.

Начните с небольшого набора сигналов, которые объясняют и объём, и намерение:

  • Запросы в минуту (в целом и по ключу)
  • Доля 429 (заблокированные запросы) и 5xx (боли бэкенда)
  • Повторяющиеся всплески 401/403 (плохие ключи, перебор учётных данных, неправильно настроенные клиенты)
  • Топ эндпойнтов по объёму и по стоимости (долгие запросы, тяжёлые экспорты)
  • Новые или неожиданные эндпойнты в топ‑10

Чтобы отделить «плохой трафик» от «мы только что выпустили фичу», добавьте контекст на дашборды: время деплоя, изменения feature‑флагов, маркетинговые рассылки. Если трафик подпрыгнул сразу после релиза, а соотношение 429/5xx остаётся нормальным, это чаще рост, а не злоупотребление. Если же скачок сосредоточен на одном ключе, одном диапазоне IP или одном тяжёлом эндпойнте — это подозрительно.

Алерты должны быть скучными. Используйте пороги и cooldown, чтобы вас не звонили каждую минуту по одной и той же причине:

  • Доля 429 выше X% в течение 10 минут — уведомить раз в час
  • 5xx выше Y% в течение 5 минут — незамедлительно поднять тревогу
  • Один ключ превысил квоту более чем на Z% в течение 15 минут — начать расследование
  • Всплески 401/403 выше N/min — пометить как возможное злоупотребление

Когда алерт срабатывает, держите короткую заметку инцидента: что изменилось, что вы увидели (топ ключей/эндпойнтов) и что вы изменили (лимиты, кеши, временные блоки). Со временем эти заметки станут вашей реальной инструкцией.

Пример: вы запустили новый поисковый эндпойнт и трафик удвоился. Если вызовы распределены по многим ключам и затрагивают в основном этот эндпойнт, повысьте пер‑ключевую квоту немного и оптимизируйте эндпойнт. Если же один ключ неустанно вызывает экспорт и создаёт высокую задержку, ограничьте этот эндпойнт отдельно и свяжитесь с владельцем ключа.

Быстрая проверочная таблица: sanity checks до и после релиза

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

Хорошая настройка — скучная, когда работает. Этот чеклист ловит проблемы, которые обычно создают ложные срабатывания или оставляют очевидные дыры.

Перед выпуском нового эндпойнта

Проверьте в staging и сразу после запуска:

  • Идентичность: убедитесь, что лимитер опирается на правильный ключ (сначала API‑ключ, потом пользователь или IP как fallback) и что ротированные ключи не наследуют старые штрафы.
  • Лимиты: установите дефолтную квоту по ключу, затем скорректируйте по стоимости эндпойнта (дешёвый read vs дорогая запись) и ожидаемым всплескам.
  • Ответы: возвращайте понятный статус и информацию для восстановления (время повтора, оставшийся бюджет, стабильный код ошибки).
  • Логи: логируйте, кто был ограничен (ключ/пользователь/IP), какой маршрут, какое правило сработало и request ID для поддержки.
  • Обход: держите экстренный allowlist для мониторинга и доверенных интеграций.

Если вы используете AppMaster, относитесь к каждому новому эндпойнту как к решению по стоимости: простой lookup может быть щедрым, а всё, что запускает тяжёлую бизнес‑логику, должно начинаться строже.

При инциденте (злоупотребление или резкий рост трафика)

Защитите бэкенд и дайте реальным пользователям восстановиться:

  • Временно повышайте капы только для наименее рискованных маршрутов (обычно чтения) и смотрите за ошибками.
  • Добавьте короткий allowlist для известных хороших клиентов на время расследования.
  • Ужесточайте конкретные рискованные маршруты вместо понижения глобальных лимитов.
  • Включите сильную идентификацию (обязательные API‑ключи, меньше опоры на IP), чтобы не блокировать общие сети.
  • Снимите выборки: топ‑ключи, топ‑IP, user agent'ы и примеры полезных payload'ов.

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

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

Пример сценаия: как защитить публичный API, не ломая пользователей

Разделяйте публичные и административные нагрузки
Создавайте внутренние админ‑инструменты, которые остаются отзывчивыми даже при всплесках публичного трафика.
Попробовать AppMaster

Представьте публичный API, которым пользуются два приложения: клиентский портал (высокий объём, стабильный трафик) и внутренний админ‑инструмент (низкий объём, но мощные действия). Оба используют API‑ключи, а портал также имеет endpoint логина для конечных пользователей.

Однажды партнёр выпускает багнутую интеграцию, которая начинает ретраить неудачные запросы в tight loop — 200 запросов в секунду с одного API‑ключа. Без защитного слоя этот ключ может заглушить всех остальных.

Лимиты по ключу содержат размах. Багнутый ключ достигает минутного капа, получает 429, а остальные клиенты продолжают работать. У вас может быть отдельный, более низкий лимит для дорогих эндпойнтов (например, экспорты), чтобы даже «разрешённый» трафик не перегрузил базу.

Одновременно на эндпойнт авторизации начинает приходить brute‑force. Вместо блокировки всего IP‑диапазона (что бьёт по реальным пользователям за NAT) вы сначала замедляете попытки, а затем блокируете по поведению: слишком много неудачных попыток по учётной записи плюс по IP за короткое окно. Атакующий получает прогрессивно увеличивающиеся задержки, затем временную блокировку.

Реальный пользователь, который просто ошибся при вводе пароля несколько раз, может восстановиться, потому что ответы понятные и предсказуемые:

  • 429 с Retry-After, чтобы клиент знал, когда пробовать снова
  • Короткая временная блокировка (например, 10–15 минут), а не вечный бан
  • Согласованные сообщения об ошибке, которые не выдают, существует ли аккаунт

В ходе инцидента вы смотрите метрики:

  • Доля 429 по ключу и эндпойнту
  • Частота ошибок в авторизации и количество блокировок
  • P95 latency и загрузка CPU базы данных
  • Количество уникальных затронутых ключей (должно быть мало)

Так выглядит защитное ограничение, которое ограждает бэкенд и не наказывает нормальных пользователей.

Следующие шаги: заведите простую политику и итеративно улучшайте

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

Надёжная первая версия обычно включает три части:

  • Базовый per‑key лимит (запросы в минуту), покрывающий большинство эндпойнтов
  • Более жёсткие капы для дорогих эндпойнтов (поиск, экспорты, загрузки, сложные отчёты)
  • Понятные 429 с кратким сообщением, объясняющим, что делать дальше

Добавляйте блокировки только там, где риск злоупотребления высок и намерение легко определить. Типичные кандидаты: регистрация, логин, сброс пароля, создание токенов. Держите блокировки короткими (минуты, не дни) и отдавайте предпочтение прогрессивным мерам: сначала замедление, потом временная блокировка, затем более строгая проверка.

Опишите политику простым языком, чтобы поддержка могла объяснять её без помощи инженеров. Укажите, что лимитируется (по API‑ключу, по IP, по аккаунту), окно ресета и как клиент может восстановиться.

Если вы реализуете это при создании нового бэкенда, AppMaster может подойти: вы можете визуально создавать API, определять бизнес‑процессы (включая счётчики и решения о блокировке), развёртывать в облако или экспортировать сгенерированный исходный код, когда нужен полный контроль.

Легко начать
Создай что-то невероятное

Экспериментируйте с AppMaster с бесплатной подпиской.
Как только вы будете готовы, вы сможете выбрать подходящий платный план.

Попробовать AppMaster