Serviço de implementação de rate limiting adaptativo em Nginx para APIs com backing store Redis — implementação sob medida

Por · Publicado em · 7 min de leitura

Pilhas de papéis e pastas arquivadas em preto e branco, vistas de frente
Sugere organização e controle — metáfora para limites e consistência em APIs. Foto: myrfa / Pixabay

Serviço de implementação de rate limiting adaptativo em Nginx para APIs com backing store Redis. O objetivo é conter abusos sem bloquear clientes legítimos, ajustando limites por rota, plano, bursts, taxa de erros e uso recente. A solução funciona em múltiplas instâncias Nginx e mantém contadores consistentes no Redis.

O que é rate limiting adaptativo em Nginx com Redis

Rate limiting adaptativo é aplicar limites que se ajustam ao comportamento do cliente e ao estado da API. Em Nginx, isso pode ser feito com scripts (Lua via OpenResty ou njs) consultando e atualizando contadores no Redis.

Com Redis, os limites funcionam de forma consistente em vários Nginx. Dá para definir chaves por API key, IP, rota, escopo OAuth ou tenant, e devolver 429 com cabeçalhos como X-RateLimit-Remaining e Retry-After.

Para quem este serviço faz sentido

O serviço é indicado para APIs REST ou GraphQL que sofrem bursts, scraping agressivo, integrações de terceiros imprevisíveis ou precisam de fairness entre planos.

Também ajuda a proteger endpoints sensíveis como login, checkout e webhooks. Em segurança de APIs, o limitador complementa autenticação forte e mTLS. Se você busca mTLS entre Nginx e serviços, veja este passo a passo prático em Docker Compose: mTLS com smallstep.

Como funciona a implementação na prática

A implementação combina Nginx como proxy reverso e Redis como store dos contadores. O Nginx chama lógica de decisão (Lua em OpenResty ou njs) para incrementar chaves, ler janelas e decidir permitir, atrasar ou bloquear.

As chaves usam TTL para delimitar janelas. Para consistência e performance, operações em Redis são atômicas via scripts, com pipeline e conexões persistentes. Cabeçalhos de resposta expõem limites e tempo de reset ao cliente.

Quais políticas adaptativas podemos aplicar?

As políticas variam por rota, plano e risco. É possível ajustar refill do bucket, penalizar bursts e aumentar tolerância para clientes estáveis. Também dá para combinar limites por IP e por credencial para reduzir falsos positivos.

Exemplos práticos incluem: limites mais brandos para leituras cacheáveis, limites mais rígidos para login, e pesos diferentes por endpoint. Um guia complementar sobre limitadores em painéis administrativos está aqui: segurança e limitador.

  • Token bucket com refill dinâmico por plano e saúde do serviço.
  • Janela deslizante (sliding window) com penalidades graduais para bursts.
  • Ban temporário progressivo por taxa alta de 401/403/5xx.
  • Pesos por endpoint (ex.: /search consome 1, /report consome 5).
  • Listas de isenção parciais para webhooks confiáveis com auditoria.
Estratégia Como funciona Quando usar Custo em Redis
Token bucket Créditos acumulam com taxa de refill; cada chamada consome. Tráfego elástico com bursts curtos. Baixo: 1 chave por sujeito.
Janela deslizante Conta eventos em janela móvel com TTLs múltiplos. Controle fino de bursts contínuos. Médio: 2–3 chaves por sujeito.
Janela fixa Zera contadores a cada período fixo. Simplicidade e previsibilidade. Baixo: 1 chave por período.
Leaky bucket Fila com drenagem constante; pode enfileirar/atrasar. Suavizar picos sem bloquear imediatamente. Médio: 1–2 chaves + estado.

Como é o passo a passo do projeto?

O fluxo vai do diagnóstico ao rollout controlado. Cada etapa foca em reduzir riscos de bloqueios indevidos e ajustar políticas ao seu tráfego real.

Quando faz sentido, o rollout pode ser canário com métricas e rollback automatizado. Um exemplo de estratégia canária com Nginx está em: deploy canário.

  • 1) Descoberta: rotas críticas, chaves de identificação, planos e SLAs.
  • 2) Desenho das políticas e formato de chaves no Redis (TTL, prefixos).
  • 3) PoC em staging com amostragem e modo shadow (só mede).
  • 4) Testes de carga e abuso: bursts, credenciais inválidas, top keys.
  • 5) Rollout canário e ajuste fino de limites/headers.
  • 6) Documentação, runbooks e handover para o time.

Sinais de que você precisa disso agora

Alguns sintomas indicam necessidade de limitar de forma adaptativa. Eles costumam aparecer junto a reclamações de latência e instabilidade durante picos.

  • Picos de 5xx em horários de campanha ou integrações externas.
  • Fila de trabalho saturada por clientes com uso desbalanceado.
  • Spikes de login/brute force apesar de CAPTCHA ou 2FA.
  • Scraping elevado em endpoints públicos de busca.
  • Webhooks repetidos gerando processamento duplicado.

O que você recebe ao final

O resultado é um limitador alinhado ao seu risco e produto, com operação clara para o time e sinais para o cliente final via cabeçalhos. A solução é reprodutível e audível.

Para visibilidade contínua, integre métricas a um stack existente. Se você usa Prometheus e Grafana, este guia ajuda a configurar o básico: Prometheus + Grafana.

  • Políticas implementadas em Nginx com Redis, scripts e chaves versionadas.
  • Cabeçalhos de limite padronizados e páginas/JSON de erro 429.
  • Runbooks de operação: como ajustar limites e responder a incidentes.
  • Métricas e logs de decisão por rota, sujeito e motivo do bloqueio.
  • Plano de fallback: fail-open/closed, timeouts curtos e cache local.

Quanto impacta latência e disponibilidade?

O impacto depende da latência até o Redis e da política. Em rede local e com pipeline/keepalive, a sobrecarga é baixa. Em regiões distantes, prefira réplicas próximas ao Nginx.

Para disponibilidade, defina comportamento de falha: fail-open para rotas públicas de baixo risco; fail-closed para operações críticas. Mecanismos como cache curto de decisões e circuit breaker evitam cascatas. Para ataques volumétricos, combine com mitigação de rede: mitigar DDoS.

O rate limiting adaptativo em Nginx para APIs com backing store Redis permite calibrar riscos sem degradar a experiência. O design certo evita gargalos e mantém previsibilidade.

Perguntas frequentes

Qual a diferença entre limit_req do Nginx e usar Redis?

O limit_req usa memória compartilhada local do Nginx, ótima para um único nó. Com Redis, os contadores são centralizados e consistentes entre várias instâncias, permitindo políticas adaptativas, pesos por endpoint e ban progressivo sem desbalancear o cluster.

Preciso de OpenResty para isso funcionar?

Não necessariamente. OpenResty (Lua) oferece flexibilidade alta. Em muitos cenários, njs (JavaScript no Nginx) com Redis atende bem. A escolha depende de requisitos de atomicidade, complexidade da política e módulos já disponíveis no ambiente.

O que acontece se o Redis ficar indisponível?

Você pode operar em fail-open ou fail-closed por rota. Timeouts curtos, cache local de decisões e chaves de emergência em memória do Nginx reduzem impacto. A estratégia é definida conforme risco: disponibilidade máxima ou proteção mais rígida.

Consigo aplicar limites diferentes por plano de cliente?

Sim. As chaves no Redis podem incluir o plano, e a taxa de refill ou o bucket máximo varia por plano. Também é possível atribuir pesos a endpoints caros e isenções limitadas a webhooks confiáveis com auditoria e expiração.

Isso resolve ataques DDoS?

Ajuda em abusos de camada de aplicação. Para volumétricos, é preciso proteger rede e upstream. Combine com filtros L3/L4 e, se aplicável, técnicas de eBPF/XDP. Há um guia de mitigação que pode complementar sua estratégia: veja o artigo de DDoS listado acima.

Quais métricas devo acompanhar após ativar o limitador?

Acompanhe taxa de 429 por rota e por sujeito, latência e erros do Redis, tempo de decisão, top keys, percentuais de burst penalizados e conversões afetadas. Esses indicadores orientam ajustes finos e previnem bloqueios indevidos em épocas de pico.

Pronto para implementar seu rate limiter adaptativo?

Receba um diagnóstico inicial das rotas críticas, padrões de tráfego e riscos e um desenho de política sob medida em Nginx com Redis.

Pedir diagnóstico

Veja também