Rate Limiting в REST API
Введение: турникет в метро 🚇
Представь турникет: он пропускает людей по одному и не даёт толпе ворваться сразу.
Так же работает rate limiting — он защищает сервер от слишком частых запросов.
💡 Совет: лимиты нужны не для «наказать», а чтобы сервис жил стабильно.
✅ Вывод: rate limiting — это защита от перегрузки и хаоса.
Проблема → решение
Проблема: если пользователи или боты шлют слишком много запросов, сервер падает или замедляется.
Решение: вводим лимиты на скорость запросов и объясняем клиенту правила.
✅ Вывод: лимиты сохраняют качество сервиса для всех.
Чем помогает и как работает
Rate limiting помогает распределять нагрузку и не пускать «спам» запросов.
Он делает сервис стабильным, даже если кто‑то случайно перегружает API.
Как это работает:
- Клиент делает запросы.
- Сервер считает, сколько запросов уже было.
- Если лимит превышен — возвращает 429 и просит подождать.
✅ Вывод: лимиты дают серверу «дышать».
Ключевые термины (простыми словами)
- Rate limit (лимит скорости) — сколько запросов можно сделать за время.
- Quota (квота) — общий лимит на период (день/месяц).
- Burst (всплеск) — короткий пик запросов, который допустим.
- Window (окно) — отрезок времени, в котором считается лимит.
- 429 Too Many Requests — код, если лимит превышен.
- Retry-After — сколько секунд подождать перед повтором.
- RateLimit‑headers — заголовки с информацией о лимитах.
- Token Bucket — алгоритм, который допускает всплески.
Самое важное (must‑know)
- При превышении лимита возвращаем 429.
- В ответе нужен
Retry-After, чтобы клиент знал, когда повторять. - Лимиты зависят от роли/плана (гость, пользователь, премиум).
- Нельзя делать лимит «один на всех» без учёта пользователя/IP.
- Заголовки лимитов помогают клиенту не ломать API.
✅ Вывод: эти правила чаще всего спрашивают на собеседованиях.
1. Лимит запросов — что это
Назначение: защитить сервер от перегрузки.
Простыми словами: нельзя делать бесконечно много запросов за минуту.
Аналогия: турникет пропускает по одному, а не всех сразу.
Пример:
Лимит: 100 запросов в минуту🔎 Как это происходит на практике:
- Клиент отправляет запросы.
- Сервер считает их количество за минуту.
- При превышении выдаёт 429.
Характеристики:
- ✅ Лимит всегда привязан ко времени.
- ✅ Работает как защита от спама.
- ✅ Обеспечивает стабильность.
Когда использовать: всегда для публичных API.
✅ Вывод: лимит — это «охранник» API.
2. На кого ставится лимит
Назначение: честно распределить нагрузку.
Простыми словами: лимит считается отдельно для каждого пользователя.
Аналогия: у каждого человека свой билет, а не один на всех.
Пример:
По пользователю: userIdПо IP: 192.168.1.10По ключу API: api_key🔎 Как это происходит на практике:
- Клиент авторизуется или приходит с IP.
- Сервер считает лимит для конкретного клиента.
- Другие пользователи не страдают.
Характеристики:
- ✅ Лимит считается по ключу или пользователю.
- ✅ Можно вводить разные лимиты для ролей.
- ✅ Не «наказывает» всех из‑за одного клиента.
Когда использовать: когда есть логины/ключи.
✅ Вывод: лимиты должны быть персональными.
3. Алгоритмы: Fixed Window vs Token Bucket
Назначение: выбрать, как считать лимит.
Простыми словами: это способ считать «сколько уже было».
Аналогия: счётчик за минуту или копилка с жетонами.
Пример:
Fixed Window: 100 запросов за минутуToken Bucket: 100 жетонов + пополнение🔎 Как это происходит на практике:
- Fixed Window сбрасывается каждую минуту.
- Token Bucket позволяет короткий всплеск.
- Алгоритм выбирают под нагрузку.
Характеристики:
- ✅ Fixed Window проще, но даёт «скачки».
- ✅ Token Bucket гибче и лучше для всплесков.
- ✅ Алгоритм влияет на UX клиента.
Когда использовать: Token Bucket для «живых» API, Fixed Window для простых сценариев.
✅ Вывод: алгоритм — это баланс между строгостью и удобством.
4. 429 и Retry‑After
Назначение: корректно сообщить о превышении лимита.
Простыми словами: сказать клиенту «подожди».
Аналогия: табличка «очередь занята, вернитесь через 30 секунд».
Пример:
HTTP/1.1 429 Too Many RequestsRetry-After: 30🔎 Как это происходит на практике:
- Клиент превысил лимит.
- Сервер возвращает 429.
- Клиент ждёт указанное время.
Характеристики:
- ✅ 429 — стандартный код ошибки.
- ✅ Retry‑After помогает не ломать клиент.
- ✅ Без Retry‑After клиент будет повторять вслепую.
Когда использовать: всегда при превышении лимита.
✅ Вывод: 429 без Retry‑After — плохая практика.
5. Заголовки лимитов (RateLimit‑headers)
Назначение: показывать клиенту текущее состояние лимита.
Простыми словами: сколько осталось запросов и когда обновится.
Аналогия: счётчик «осталось 5 поездок».
Пример:
RateLimit-Limit: 100RateLimit-Remaining: 12RateLimit-Reset: 60🔎 Как это происходит на практике:
- Клиент получает лимит и остаток.
- Может сам замедлиться.
- Ошибок становится меньше.
Характеристики:
- ✅ Делает API дружелюбным.
- ✅ Помогает избежать 429.
- ✅ Упрощает интеграции.
Когда использовать: в публичных API и SDK.
✅ Вывод: заголовки лимитов снижают конфликт с клиентом.
6. Разные лимиты для разных планов
Назначение: поддерживать монетизацию и справедливость.
Простыми словами: бесплатным меньше, платным больше.
Аналогия: обычный и бизнес‑зал в аэропорту.
Пример:
Free: 60 req/minPro: 300 req/min🔎 Как это происходит на практике:
- Сервер узнаёт роль клиента.
- Применяет лимит по плану.
- Премиум получает больше скорости.
Характеристики:
- ✅ Лимиты завязаны на план.
- ✅ Прозрачны в документации.
- ✅ Не мешают базовым пользователям.
Когда использовать: если есть тарифы или роли.
✅ Вывод: гибкие лимиты = честное распределение ресурсов.
Сравнение алгоритмов
| Алгоритм | Плюс | Минус |
|---|---|---|
| Fixed Window | Простая реализация | «Скачки» на границах окна |
| Sliding Window | Ровнее ограничение | Сложнее считать |
| Token Bucket | Допускает всплески | Требует хранения токенов |
Часто спрашивают на собеседованиях
- Чем отличается Fixed Window от Token Bucket?
- Что означает 429 и зачем нужен Retry‑After?
- Почему лимиты должны быть персональными?
- Что такое burst и зачем он нужен?
- Какие заголовки показывают лимит и остаток?
✅ Вывод: эти вопросы показывают понимание практики, а не терминов.
Типичные ошибки
Ошибка 1: Нет 429
❌ Неправильно: возвращать 200 с ошибкой в теле.
✅ Правильно: возвращать 429.
Почему: клиент не понимает, что он в лимите.
✅ Правильно: возвращать 429.
Почему: клиент не понимает, что он в лимите.
Ошибка 2: Нет Retry‑After
❌ Неправильно: 429 без подсказки.
✅ Правильно: 429 + Retry‑After.
Почему: клиент начинает спамить повторными запросами.
✅ Правильно: 429 + Retry‑After.
Почему: клиент начинает спамить повторными запросами.
Ошибка 3: Лимит «один на всех»
❌ Неправильно: общий лимит на весь сервис.
✅ Правильно: лимит по пользователю/IP/ключу.
Почему: один клиент не должен ломать всех.
✅ Правильно: лимит по пользователю/IP/ключу.
Почему: один клиент не должен ломать всех.
Ошибка 4: Слишком жёсткий лимит
❌ Неправильно: 5 req/min для всех.
✅ Правильно: разумные лимиты + burst.
Почему: это ломает UX.
✅ Правильно: разумные лимиты + burst.
Почему: это ломает UX.
Ошибка 5: Нет заголовков лимита
❌ Неправильно: скрывать лимиты.
✅ Правильно: показывать RateLimit‑headers.
Почему: клиент не может подстроиться.
✅ Правильно: показывать RateLimit‑headers.
Почему: клиент не может подстроиться.
Ошибка 6: Нет правил для ролей
❌ Неправильно: одинаковые лимиты для всех планов.
✅ Правильно: разные лимиты по ролям.
Почему: иначе платные планы теряют смысл.
✅ Правильно: разные лимиты по ролям.
Почему: иначе платные планы теряют смысл.
Best Practices
- Используй 429 + Retry‑After при превышении лимита.
- Делай лимиты персональными (по ключу, пользователю или IP).
- Добавляй заголовки
RateLimit-*. - Поддерживай burst через Token Bucket.
- Делай разные лимиты по тарифам.
- Документируй правила лимитов.
Заключение
Rate limiting — это защита качества сервиса.
Он делает API стабильным и понятным для клиентов.
Если правила прозрачны — интеграция идёт без конфликтов.
✅ Вывод: лимиты — обязательный элемент зрелого API.