коротко

Лимиты на количество запросов нужны для трёх вещей: защита от перегруза (один клиент не уронит сервис всем), защита от abuse (перебор паролей, скрейпинг) и справедливость (никто не захватывает все ресурсы). Это нефункциональное требование. Rate limit — «не больше N запросов за период» (100 в минуту). Throttling — мягкое притормаживание сверх лимита вместо жёсткого отказа. Quota — лимит на длинный период (10 000 в месяц), часто по тарифу. На превышение сервер отвечает 429 Too Many Requests и подсказывает заголовками, сколько осталось (X-RateLimit-*) и когда можно повторить (Retry-After). Аналитик обязан задать: лимит на кого, сколько, что вернуть при превышении и зависит ли он от тарифа.

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

Зачем вообще лимиты

Лимит на запросы решает три разные задачи, и полезно их различать, потому что от задачи зависят и числа, и реакция.

Защита от перегруза. Ровно моя история: ресурсы сервиса конечны, и без потолка один клиент (по ошибке или из-за бага) способен выесть их целиком и уронить сервис для всех. Лимит ставит каждому потолок, за которым его трафик упирается в стену, а не в общие ресурсы.

Защита от abuse. Перебор паролей (brute force), массовый скрейпинг данных, спам через формы. Лимит на попытки логина с одного адреса превращает перебор из «миллион попыток в час» в «пять и стоп».

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

Rate limit, throttling, quota: разница

Три похожих слова, которые путают, хотя смысл разный.

Rate limit — жёсткий потолок частоты на коротком окне: «не больше 100 запросов в минуту». Превысил — получи отказ (429), приходи позже.

Throttling — мягкая реакция: вместо отказа сервис притормаживает — обслуживает медленнее, ставит запросы в очередь, растягивает во времени. Не «нельзя», а «помедленнее». Иногда throttling и rate limit используют как синонимы, но точнее так: rate limit — это правило (сколько можно), throttling — одна из реакций на его превышение (придержать вместо того, чтобы отказать).

Quota — лимит на длинный период, обычно бизнесовый: «10 000 запросов в месяц на вашем тарифе». Это уже не про мгновенный перегруз, а про объём потребления и деньги.

ПонятиеПро чтоПериодПример
Rate limitчастота, жёсткий потолоксекунды-минуты100 запросов / минуту
Throttlingмягкое притормаживаниев моментезамедлить, поставить в очередь
Quotaобъём, обычно по тарифудень-месяц10 000 запросов / месяц

Алгоритмы на пальцах

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

Token bucket («ведро с жетонами»). Представьте ведро, в которое с постоянной скоростью капают жетоны — скажем, по одному в секунду, но не больше 100 за раз. Каждый запрос забирает жетон. Есть жетон — проходи; ведро пусто — отказ. Прелесть в том, что жетоны копятся: если вы час молчали, ведро полное, и можно сделать всплеск из 100 запросов разом, а дальше — со скоростью капания. Это разрешает короткие всплески, но держит средний темп. Самый ходовой подход.

Fixed window («фиксированное окно»). Считаем запросы в жёстких отрезках: с 12:00:00 до 12:00:59 — не больше 100. Просто, но есть подвох на стыке: 100 запросов в 12:00:59 и ещё 100 в 12:01:00 — формально оба окна в норме, а по факту 200 за две секунды.

Sliding window («скользящее окно»). Чинит стык: окно не привязано к круглым минутам, а скользит — «сколько запросов за последние 60 секунд от текущего момента». Считать чуть дороже, зато всплеск на границе так не проскочит.

Код 429 и заголовки

Когда лимит превышен, сервер отвечает 429 Too Many Requests. Но просто отказать — грубо: клиент не знает, сколько ждать, и будет долбить вслепую. Поэтому к 429 прикладывают служебные заголовки.

HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1716552000
Content-Type: application/json

{
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "Превышен лимит запросов, повторите через 30 секунд"
}

Retry-After — через сколько секунд можно повторить. Главный заголовок: воспитанный клиент читает его и ждёт ровно столько, а не гадает. X-RateLimit-Limit — каков лимит (100). X-RateLimit-Remaining — сколько осталось в текущем окне (0 — всё). X-RateLimit-Reset — когда окно обнулится. По этим заголовкам клиент может вообще не доводить до 429 — притормозить заранее, увидев, что remaining близко к нулю. Сам код 429 относится к ошибкам, которые можно ретраить (после паузы) — подробнее про это в записи про ошибки в API.

Что аналитик закладывает в требования

Лимит не появляется сам — это решение, и принять его должен аналитик, явно, в спеке. Четыре обязательных вопроса:

  • Лимит на кого. На пользователя? На API-ключ? На IP-адрес? На эндпоинт? Лимит на логин обычно по IP (против перебора), на бизнес-API — по ключу/тарифу. Это разные счётчики.
  • Сколько и за какой период. Конкретные числа: 100/минуту, 10 000/месяц. «Разумный лимит» — не требование, это перекладывание решения на разработчика.
  • Что вернуть при превышении. 429 с какими заголовками? Есть ли Retry-After? Какой текст увидит пользователь? Жёсткий отказ или мягкое throttling?
  • Зависит ли от тарифа. Если у продукта платные планы — у каждого свой лимит, и это таблица в спеке, а не «потом разберёмся».
ТарифRate limitМесячная квота
Free10 запросов / мин1 000 / месяц
Pro100 запросов / мин50 000 / месяц
Enterprise1 000 запросов / минбез квоты

Backpressure: лимит со стороны получателя

Близкое понятие — backpressure («обратное давление»): когда получатель не справляется с потоком, он сигналит отправителю «притормози», и нагрузка регулируется по всей цепочке, а не копится до взрыва. Rate limit можно считать backpressure на входе в API. В асинхронных системах с очередями та же идея работает естественно — очередь сама гасит всплески, давая консьюмеру читать в своём темпе; про это в записи про синхронную и асинхронную интеграцию.

Лимиты — это часть SLA

Лимит и обещание доступности связаны напрямую. Если вы гарантируете клиенту определённую доступность и время ответа, лимиты — один из инструментов это обещание держать: именно они не дают одному потребителю просадить сервис для всех. Поэтому числа лимитов и условия SLA проектируют вместе, а не порознь — подробнее в записи про SLA, SLO и инциденты.

Откуда это взялось

Лимиты существовали и раньше, но нормой публичных API их во многом сделал Twitter API около 2008 года: у него был жёсткий потолок запросов в час на пользователя, и заголовки в духе X-RateLimit-* стали ориентиром для индустрии. Вокруг них выросла целая культура — разработчики, интегрировавшиеся с Twitter, первыми массово научились читать «сколько осталось» и «когда сброс». Позже это подхватили GitHub, Stripe и почти все крупные API, а 429 Too Many Requests закрепили официально в RFC 6585 (2012).

Как это спрашивают на собесе

Формулировки: «Зачем нужны rate limits?», «Чем rate limit отличается от quota?», «Что вернуть клиенту при превышении лимита?», «Расскажите про token bucket», «На кого вешать лимит?». Сильный ответ называет три цели (перегруз, abuse, справедливость), разводит rate limit / throttling / quota, знает про 429 и Retry-After, объясняет token bucket на аналогии с ведром (всплески разрешены, средний темп держится) и — что отличает аналитика — перечисляет, что нужно заложить в требования: на кого, сколько, что вернуть, зависит ли от тарифа. Упоминание, что лимиты — это НФТ и часть SLA, добавляет веса.

Частые вопросы

Чем rate limit отличается от quota?

Периодом и назначением. Rate limit — жёсткий потолок частоты на коротком окне (100 запросов в минуту), его задача — защита от перегруза и всплесков прямо сейчас. Quota — лимит на длинный период (10 000 в месяц), это уже про объём потребления и обычно про деньги: разные тарифы дают разные квоты. У одного API часто действуют оба одновременно: rate limit бережёт сервис в моменте, quota ограничивает суммарное потребление за период.

Что сервер должен вернуть при превышении лимита?

Код 429 Too Many Requests и служебные заголовки. Главный — Retry-After: через сколько секунд можно повторить, чтобы клиент ждал осознанно, а не долбил вслепую. Полезны и X-RateLimit-Limit / Remaining / Reset: каков лимит, сколько осталось, когда окно обнулится — по ним воспитанный клиент притормозит заранее, не доводя до отказа. В теле — машинный code и человеческое сообщение, как у любой ошибки API.

Что такое token bucket простыми словами?

Это «ведро с жетонами». В ведро с постоянной скоростью капают жетоны, но не больше фиксированного максимума. Каждый запрос забирает один жетон: есть жетон — проходи, ведро пусто — отказ. Поскольку жетоны копятся в простое, алгоритм разрешает короткие всплески (израсходовать накопленное разом), но удерживает средний темп на скорости капания. Это самый распространённый способ считать лимит — он гибче жёсткого окна и хорошо переносит неравномерный трафик.