← Back to notes

L7 Security:
Rate Limiting


Теория

Зачем нужен rate limiting

  • защита от brute force и credential stuffing;
  • ограничение API abuse и квоты;
  • смягчение L7 flood;
  • контроль стоимости дорогих endpoints.

Алгоритмы

Token Bucket

Ёмкость b, refill rate r. Запрос тратит токен. При накопленных токенах допускает controlled burst до b. RFC 2697 описывает srTCM (single rate three color marker), близкая модель.

Leaky Bucket

Запросы вытекают с фиксированной скоростью; избыток — drop или delay. NGINX limit_req реализован как leaky bucket: nodelay отдаёт burst немедленно, без nodelay — задерживает.

Fixed Window

Счётчик в фиксированном интервале. Дёшево; boundary burst на стыке окон даёт до 2× rate.

Sliding Window

Аппроксимация: count = prev × (1 elapsed/window) + current. Меньше boundary-артефактов, дороже по состоянию.

Sliding Log

Хранит timestamp каждого запроса. Точнее всех; O(N) память.


Distributed Rate Limiting

Проблемы распределённого лимитера:

  • race conditions при конкурентных обновлениях;
  • consistency между узлами;
  • replication lag (особенно при async replication);
  • hot keys и неравномерная нагрузка.

Рабочие паттерны:

  • sharded counters;
  • consistent hashing по limit key;
  • local + global hybrid (локальный токен-бакет + глобальный decision service).

Ключевые параметры

  • limit key: IP / user / API token / route + token.
  • burst: сколько допускаем кратковременно сверх steady rate.
  • delay vs drop: деградировать мягко или жёстко отбрасывать.
  • sliding granularity: точность окна vs стоимость вычисления.

Что нужно уметь объяснить

Почему distributed rate limiting сложнее локального?

Локальный лимитер видит только локальный поток.
Distributed лимитер должен синхронно (или квазисинхронно) согласовать состояние между узлами под гонками и задержками репликации.

Почему ключ лимита важнее «самого алгоритма»?

Плохой key (IP за NAT, общий service token) даёт или массовые FP, или бесполезно слабую защиту.

Когда лучше delay, а когда drop?

  • delay: когда важно мягко сгладить всплеск.
  • drop/429: когда нужно быстро освободить ресурсы origin.

Практика

1. Базовый лимит в NGINX

limit_req_zone $binary_remote_addr zone=api_limit:20m rate=20r/s;

location /api/ {
    limit_req zone=api_limit burst=40 nodelay;
    proxy_pass http://backend;
}

2. Проверьте поведение на burst

wrk -t8 -c400 -d30s https://example.com/api/

Смотрите:

  • долю 429/503;
  • latency p95/p99;
  • CPU на edge/origin.

3. Разделите ключи лимита

Сравните:

  • только IP;
  • API token;
  • composite key (route + token).

4. Для distributed-модели разделите local/global слой

  • local limiter на edge (быстрый fail-fast);
  • global limiter для account-wide quota/policy.

HTTP-протокол

  • статус: 429 Too Many Requests (RFC 6585);
  • Retry-After (RFC 9110 §10.2.3) — секунды или HTTP-date;
  • RateLimit / RateLimit-Policy headers — RFC 9239; X-RateLimit-* остаются распространёнными, но нестандартными vendor headers.

Ссылки

L7 Security: Rate Limiting | Aleksandr Suprun