Pular para o conteúdo principal

Rate Limiting e Throttling: Protegendo APIs de Sobrecarga e Abuso

Publicado em 21 de dezembro de 202525 min de leitura
Imagem de tecnologia relacionada ao artigo rate-limiting-throttling-apis

Qualquer API pública, cedo ou tarde, encara o mesmo desafio: como lidar com um volume excessivo de requisições? Pode ser um desenvolvedor bem-intencionado que disparou um loop infinito por engano, um crawler agressivo tentando indexar todo o seu conteúdo ou, no pior dos casos, um atacante tentando derrubar seu serviço com um ataque DDoS. O resultado é sempre uma infraestrutura sobrecarregada e usuários legítimos sendo prejudicados.

O rate limiting surge como a defesa essencial para impor limites à frequência dessas requisições. É a ferramenta que protege sua estabilidade e garante que os recursos sejam distribuídos de forma justa entre todos os usuários. Neste artigo, vamos mergulhar nos algoritmos que fazem isso acontecer, como o token bucket e o leaky bucket, e entender como implementar essas barreiras em sistemas de produção sem comprometer a experiência do usuário.

1. Por Que Rate Limiting É Necessário

1.1 Proteção Contra Sobrecarga

Mesmo clientes legítimos podem sobrecarregar sua API. Um desenvolvedor pode acidentalmente criar um loop que faz milhares de requisições por segundo. Uma migração de dados pode gerar picos de uso muito acima do normal. Sem rate limiting, esses cenários podem derrubar toda a infraestrutura, afetando todos os usuários. Rate limiting funciona como uma válvula de segurança que impede que qualquer usuário individual consuma recursos desproporcionais.

1.2 Proteção Contra Abuso

Atacantes usam volume de requisições como arma. Ataques DDoS (Distributed Denial of Service) tentam esgotar seus recursos com requisições, tornando o serviço indisponível. Brute force attacks tentam milhares de senhas por segundo. Scrapers agressivos copiam seu conteúdo sem permissão. Rate limiting não é uma solução completa para todos esses problemas, mas é uma linha de defesa fundamental que aumenta significativamente o custo para atacantes.

1.3 Garantia de Fairness

Sem limites, usuários que fazem muitas requisições (power users ou integrações programáticas) podem degradar a experiência de usuários casuais. Rate limiting garante que cada usuário receba uma fatia justa da capacidade disponível. Isso é especialmente importante para APIs freemium, onde usuários gratuitos devem ter acesso funcional mesmo quando grandes clientes enterprise estão consumindo muito.

2. Algoritmos de Rate Limiting

2.1 Token Bucket

O algoritmo token bucket é provavelmente o mais usado na indústria. Imagine um balde que contém tokens. Cada requisição consome um token. Tokens são adicionados ao balde a uma taxa constante (por exemplo, 10 por segundo). O balde tem capacidade máxima; tokens adicionados quando está cheio são descartados. Quando uma requisição chega e não há tokens, ela é rejeitada ou atrasada.

A beleza do token bucket é que ele naturalmente permite bursts curtos. Se o bucket está cheio com 100 tokens e um cliente fez poucas requisições recentemente, ele pode fazer 100 requisições rapidamente antes de ser limitado. Isso acomoda padrões de uso legítimos onde requisições vêm em rajadas. A taxa média de longo prazo é limitada pela taxa de adição de tokens, mas bursts curtos são permitidos até a capacidade do bucket.

2.2 Leaky Bucket

Já o leaky bucket (ou "balde furado") funciona com uma lógica inversa: as requisições entram no balde e ele as "vaza" para o processamento a uma taxa rigorosamente constante. Se as requisições chegam rápido demais e o balde enche, o excesso simplesmente derrama — ou seja, as novas requisições são rejeitadas até que haja espaço novamente.

Diferente do token bucket, o leaky bucket é implacável com os bursts. Ele força uma suavização total do tráfego (traffic shaping), o que o torna ideal para proteger sistemas legados ou backends sensíveis que não lidam bem com picos repentinos de carga. Na prática, muitos desenvolvedores confundem os dois termos, mas a diferença chave está em como você lida com as rajadas: o leaky bucket as achata, enquanto o token bucket as acomoda até certo limite.

2.3 Fixed Window

O algoritmo mais simples é o fixed window: você define uma janela de tempo (por exemplo, 1 minuto) e um limite (100 requisições), e cada cliente pode fazer no máximo 100 requisições por janela. A implementação é trivial: mantenha um contador por cliente, incremente a cada requisição, resete quando a janela muda.

A desvantagem é que permite bursts na transição de janelas. Se alguém faz 100 requisições no último segundo de uma janela e 100 no primeiro segundo da próxima, efetivamente fez 200 requisições em dois segundos — o dobro do limite pretendido. Para muitos casos de uso isso é aceitável, mas para limites rigorosos pode ser problema.

2.4 Sliding Window Log

Para eliminar o problema de transição de janelas, você pode manter um log de todas as requisições recentes. Para cada nova requisição, descarte entradas mais antigas que a janela, conte as restantes, e compare com o limite. Isso dá comportamento preciso, mas tem custo de memória proporcional ao número de requisições por janela — impraticável para limites altos ou muitos usuários.

2.5 Sliding Window Counter

Uma aproximação híbrida: combine o contador da janela atual com uma fração ponderada da janela anterior. Se estamos 30% dentro da janela atual, o limite efetivo considera 100% da janela atual mais 70% da anterior. Isso suaviza as transições sem o custo de memória do logging completo. É a abordagem usada por muitos sistemas de produção como Cloudflare e Kong.

2.6 Generic Cell Rate Algorithm (GCRA)

O GCRA é um algoritmo sofisticado originário das redes ATM (Asynchronous Transfer Mode). Ele é matematicamente equivalente ao Leaky Bucket, mas implementado de forma muito mais eficiente para sistemas distribuídos. Em vez de gerenciar um "balde" com tokens que precisam ser incrementados periodicamente (o que é difícil em escala), o GCRA simplesmente rastreia o TAT (Theoretical Arrival Time): o horário em que a próxima requisição deveria chegar para estar dentro da taxa.

Se uma requisição chega antes do TAT ajustado pela tolerância de burst, ela é rejeitada. A grande vantagem é que ele requer apenas uma única variável persistente por cliente, eliminando a necessidade de processos de background para "encher" buckets. É o algoritmo por trás de implementações de alta performance como o redis-cell.

3. Onde Implementar Rate Limiting

3.1 Gateway/Proxy Level

Implementar rate limiting no API gateway (Kong, NGINX, Envoy) ou load balancer tem a vantagem de proteger todos os serviços atrás dele com configuração centralizada. Requisições rejeitadas não chegam aos backends, economizando recursos. A desvantagem é que o gateway pode não ter contexto suficiente para limites sofisticados (por user, por plano, por endpoint).

3.2 Application Level

Rate limiting na aplicação permite decisões mais sofisticadas baseadas em lógica de negócio. Você pode ter limites diferentes por tier de cliente, por endpoint, ou por tipo de operação. A desvantagem é que requisições chegam à aplicação antes de serem rejeitadas, consumindo algum processamento, e cada microserviço pode precisar de sua própria implementação.

3.3 Distributed Rate Limiting

Em sistemas distribuídos com múltiplas instâncias, rate limiting local não é suficiente — um cliente poderia atingir cada instância separadamente. Rate limiting precisa ser coordenado, tipicamente usando um store centralizado como Redis. Cada instância verifica e incrementa contadores compartilhados.

O Poder do Redis + Lua Scripts

Para evitar condições de corrida (race conditions) em sistemas distribuídos, a verificação e o incremento do limite devem ser atômicos. A forma mais comum de fazer isso é via Lua scripts executados dentro do Redis.

O script Lua garante que nenhuma outra operação altere o contador entre o momento em que você lê o valor e o momento em que o incrementa. Isso evita o clássico bug onde dois servidores permitem uma requisição simultaneamente quando restava apenas 1 token no limite global.

4. Considerações Práticas

4.1 Identificação de Clientes

A escolha do identificador para aplicação de limites é uma das decisões mais críticas no design de um sistema de rate limiting. Por qual identificador você limita? Por IP? Por API key? Por user ID? Cada escolha tem trade-offs significativos que afetam diretamente a eficácia e a justiça do sistema de limitação.

Limitar por IP é a abordagem mais comum e direta, mas também a mais problemática. IPs podem ser compartilhados por múltiplos usuários legítimos devido a NAT (Network Address Translation), VPNs, proxies corporativos ou redes de instituições como universidades e empresas. Nesse cenário, limitar por IP pode afetar negativamente múltiplos usuários legítimos que compartilham o mesmo endereço IP. Por outro lado, é a única opção disponível para limitar requisições de clientes não autenticados.

API keys oferecem uma identificação muito mais precisa, pois são únicas por cliente ou aplicação. Elas exigem autenticação prévia, o que garante que você está lidando com um cliente registrado. No entanto, esse método só é eficaz para clientes que já passaram pelo processo de registro e obtenção de credenciais.

User ID é o método mais preciso de todos, pois identifica o usuário individualmente, independentemente do dispositivo ou IP usado. No entanto, esse tipo de limitação exige que o usuário esteja autenticado no sistema, o que nem sempre é possível ou desejável, especialmente para endpoints públicos.

O desafio adicional é que atacantes sofisticados podem contornar esses limites rotacionando IPs usando botnets ou VPNs, ou criando múltiplas contas para aumentar artificialmente sua cota total. Por isso, muitos sistemas modernos usam uma combinação de identificadores e técnicas de fingerprinting para detectar e mitigar essas tentativas de contorno.

4.2 Limites por Níveis de Negócio (Tiering)

O rate limiting é também uma ferramenta de monetização. É comum ver diferentes limites para diferentes planos:

  • Plano Free: 1.000 requisições/dia.
  • Plano Pro: 50.000 requisições/dia.
  • Plano Enterprise: Ilimitado ou limites customizados por contrato.

Isso exige que o seu sistema de rate limiting consulte o banco de dados de usuários ou um cache de metadados para saber qual limite aplicar a cada requisição.

4.3 Limites Secundários (Secondary Limits)

Às vezes, um usuário tem um limite global alto, mas ainda assim pode abusar do sistema. Por exemplo, ele tem direito a 1 milhão de requisições por dia, mas tenta fazer todas elas em um único segundo.

Os Limites Secundários protegem contra isso. Você pode ter um limite de 50.000/dia E um limite de 20/segundo. O primeiro protege sua cota de negócio; o segundo protege a estabilidade imediata da CPU e do banco de dados.

5. Segurança: Como Atacantes Burlam o Rate Limiting

Atacantes sofisticados não param no primeiro 429. Eles tentam burlar os limites por meio de:

  1. Rotação de IPs: Usando proxies residenciais ou botnets para distribuir o tráfego por milhares de IPs.
  2. Manipulação de Headers: Se o seu rate limiter confia em headers como X-Forwarded-For para identificar o IP sem validação, o atacante pode simplesmente enviar valores falsos.
  3. Múltiplas Contas: Criando "contas fantasmas" para multiplicar sua cota total.

Para se defender, é necessário usar identificadores mais robustos, como Browser Fingerprinting ou exigir o uso de CAPTCHAs ou Proof-of-Work (PoW) quando um comportamento suspeito é detectado, mesmo que o limite ainda não tenha sido atingido.

4.2 Headers de Resposta

Boas APIs informam clientes sobre limites via headers. RateLimit-Limit (limite total), RateLimit-Remaining (requisições restantes), RateLimit-Reset (quando o limite reseta) permitem que clientes ajustem seu comportamento proativamente. HTTP 429 (Too Many Requests) é o status code padrão para requisições limitadas, com Retry-After header indicando quando tentar novamente.

4.3 Degradação Suave (Graceful Degradation)

Nem toda punição por excesso de taxa precisa ser um erro 429 seco. Em muitos cenários, é possível aplicar uma degradação suave. Isso pode significar servir dados levemente desatualizados que já estão em cache, retornar respostas parciais ou apenas aplicar um atraso (throttling) em vez de uma rejeição total. Essa abordagem suaviza a experiência para aquele cliente que ultrapassou o limite por pouco e ajuda a evitar o efeito de "bola de neve" nas tentativas de reconexão.

6. Caso de Estudo: A API do GitHub

O GitHub implementa um dos sistemas de rate limiting mais transparentes e robustos do mercado. Eles utilizam:

  • Limites Primários: Baseados na autenticação (5.000/hora para usuários autenticados, 60/hora para não autenticados).
  • Limites de Busca (Search): Muito mais rigorosos (30/minuto), pois a busca é uma operação custosa para o banco de dados.
  • Limites Secundários: Para evitar abusos rápidos, como criar centenas de repositórios via script em poucos segundos.

Eles informam tudo isso via headers x-ratelimit-*, o que permite que ferramentas de automação (como o Terraform ou CI/CDs) façam o backoff (espera) automático de forma elegante.

7. Métricas e Observabilidade: Medindo o Bloqueio

Você não deve apenas bloquear; deve saber quem está sendo bloqueado e por que. Métricas essenciais incluem:

  • Taxa de 429s por Minuto: Se aumentar repentinamente, pode indicar um ataque ou um bug em um cliente grande.
  • Latência do Rate Limiter: Se você usa o Redis, quanto tempo leva para verificar o limite? Se for > 5ms, o próprio rate limiter pode virar o gargalo.
  • Distribuição de Clientes Bloqueados: Quais usuários estão batendo no limite com mais frequência? Isso pode indicar a necessidade de oferecer um upgrade de plano.

7.1 Alertas e Dashboards

Configure alertas no Slack ou PagerDuty para aumentos anômalos de erros 429. Um surge de 429s muitas vezes precede uma queda total do sistema se o rate limiter não for robusto o suficiente.

8. Rate Limiting Global: O Desafio do Anycast

Em sistemas globais onde o tráfego entra por múltiplos pontos geográficos (via Anycast), manter um contador global preciso é difícil. A luz leva tempo para viajar. Se o seu Redis central está nos EUA e o tráfego entra em Singapura, a latência de verificação pode ser de 200ms por requisição — inaceitável.

Soluções modernas incluem:

  1. Edge Rate Limiting: Limites são aplicados na borda (ex: Cloudflare Workers) com sincronização assíncrona.
  2. Hashing Geográfico: Clientes de uma região sempre batem no mesmo cluster regional de rate limiting.

9. Load Shedding: O Irmão Mais Bruto do Rate Limiting

Diferente do rate limiting, que foca no usuário, o Load Shedding foca na saúde do servidor. Quando a CPU ou o tempo de resposta do servidor ultrapassa um limite crítico, o sistema começa a descartar requisições aleatoriamente (mesmo de usuários dentro da cota) para evitar uma queda catastrófica (o "morte por mil cortes"). É a defesa de última instância.

10. Estratégias no Lado do Cliente: O Backoff Exponencial

Um bom cliente de API deve saber lidar com erros 429. Se ele simplesmente tentar de novo imediatamente, ele cria uma Retry Storm, piorando a carga do servidor. A estratégia correta é o Exponential Backoff com Jitter:

  1. Falhou? Espere 1s.
  2. Falhou de novo? Espere 2s.
  3. De novo? Espere 4s.
  4. Adicione um "Jitter" (um valor aleatório) para evitar que milhares de clientes tentem se reconectar exatamente no mesmo milissegundo.

11. Implementação Algorítmica: Token Bucket do Zero

Muitos desenvolvedores usam bibliotecas prontas, mas entender como implementar o Token Bucket é um exercício valioso. O segredo é não usar um timer para adicionar tokens (o que seria ineficiente), mas calcular o número de tokens com base no tempo transcorrido desde a última requisição.

javascript
class TokenBucket {
  constructor(capacity, fillRate) {
    this.capacity = capacity;
    this.fillRate = fillRate; // tokens por segundo
    this.tokens = capacity;
    this.lastRefill = Date.now();
  }

  allowRequest(tokensRequested = 1) {
    this.refill();
    if (this.tokens >= tokensRequested) {
      this.tokens -= tokensRequested;
      return true;
    }
    return false;
  }

  refill() {
    const now = Date.now();
    const elapsed = (now - this.lastRefill) / 1000; // em segundos
    const newTokens = elapsed * this.fillRate;
    
    this.tokens = Math.min(this.capacity, this.tokens + newTokens);
    this.lastRefill = now;
  }
}

Essa abordagem é extremamente performática e fácil de persistir em um banco de dados ou cache distribuído.

12. Rate Limiting Baseado em Prioridade (VIP Users)

Nem todas as requisições são iguais. Em sistemas de missão crítica, você pode querer priorizar usuários pagantes ou processos internos sobre tráfego gratuito quando o sistema está operando perto do limite.

Isso é feito adicionando um sistema de filas com prioridade. Requisições de usuários VIP consomem de um bucket separado ou têm uma taxa de recarga maior. Em caso de sobrecarga extrema, o Load Shedding descarta primeiro as requisições de menor prioridade, garantindo que os clientes mais importantes não sintam a instabilidade.

13. O Teorema CAP e o Rate Limiting

Pode parecer estranho falar de teorema CAP para limites de tokens, mas em sistemas distribuídos, você enfrenta o mesmo trade-off:

  • Consistência (C): Cada requisição em qualquer lugar do mundo deve saber o estado exato dos tokens globais. Isso exige que cada requisição espere por uma sincronização (latência altíssima).
  • Disponibilidade (A): Se o seu servidor de cache (Redis) cair, você deve continuar permitindo requisições (possivelmente estourando o limite)?
  • Tolerância a Partição (P): O que acontece se a rede entre suas instâncias falhar?

13. Rate Limiting em Ambiente Serverless

Em plataformas como AWS Lambda ou Vercel Functions, você não tem um servidor persistente para manter contadores. Cada execução é isolada. Aqui, o uso de um cache externo (Redis) é obrigatório, mas a latência de conexão pode ser um problema.

Soluções como o Upstash (Redis focado em serverless) oferecem uma API REST para verificar os limites, o que é muito mais eficiente para lambdas do que manter conexões TCP/IP pesadas. Outra alternativa é usar o Edge Middleware, que executa a lógica de limite antes mesmo da função serverless ser disparada, economizando custos de execução.

14. Algoritmo de Log de Janela Móvel (Sliding Window Log)

Vimos que o log de janela móvel é o mais preciso. Veja como ele funciona internamente:

  1. Para cada requisição, salvamos o timestamp em um Sorted Set no Redis.
  2. Removemos todos os timestamps mais velhos que a janela atual (now - 60s).
  3. Contamos quantos timestamps restaram.
  4. Se a contagem for menor que o limite, permitimos a requisição e adicionamos o novo timestamp.

Embora seja preciso ao milissegundo, ele consome muita memória se você tiver milhares de requisições por segundo por usuário. Use-o apenas quando a precisão absoluta for inegociável.

15. Rate Limiting em Microserviços: O Padrão Sidecar

Em arquiteturas de microserviços, o rate limiting pode ser delegado ao Service Mesh (como o Istio ou Linkerd). No padrão Sidecar, cada pod da aplicação tem um processo auxiliar que intercepta todo o tráfego de entrada e saída.

A vantagem é que o desenvolvedor do microserviço não precisa se preocupar com a lógica de limites; ela é configurada de forma declarativa via Kubernetes. O sidecar conversa com um serviço de quórum ou cache global para validar os limites de forma transparente e com baixíssima latência local.

15. Segurança Avançada: Análise Comportamental

Limites estáticos (ex: 100 req/min) são fáceis de burlar se o atacante souber o valor. A Análise Comportamental usa modelos de Machine Learning para detectar anomalias. Se um usuário normalmente acessa apenas 5 páginas por minuto e repentinamente começa a acessar 80, o sistema pode aplicar um soft limit (desafio CAPTCHA) mesmo que ele ainda não tenha batido no limite estático de 100. Isso protege contra scrapers que tentam "voar abaixo do radar".

16. Implementação Prática: Node.js + Express + Redis

Veja um exemplo simplificado de como implementar o padrão Fixed Window usando Node.js e Redis com atomicidade:

javascript
const express = require('express');
const redis = require('redis');
const client = redis.createClient();

const app = express();

const rateLimiter = async (req, res, next) => {
  const ip = req.ip;
  const key = `rate-limit:${ip}`;
  const LIMIT = 100; // requisições
  const WINDOW = 60; // segundos

  try {
    const current = await client.incr(key);
    
    if (current === 1) {
      await client.expire(key, WINDOW);
    }

    if (current > LIMIT) {
      return res.status(429).json({
        error: 'Too Many Requests',
        retryAfter: await client.ttl(key)
      });
    }

    next();
  } catch (err) {
    // Falha aberto em caso de erro no Redis
    console.error('Redis Error:', err);
    next();
  }
};

app.use(rateLimiter);

Este código usa o comando INCR do Redis, que é atômico, garantindo que o contador seja incrementado corretamente mesmo com múltiplas requisições paralelas.

13. Conclusão

Mais do que apenas uma barreira contra abusos, o rate limiting é uma declaração de como seu sistema valoriza a disponibilidade e a justiça. Implementá-lo corretamente exige ir além da escolha do algoritmo; requer transparência com o desenvolvedor que consome sua API e uma monitoria constante para ajustar esses limites conforme o uso evolui.

Um sistema de limites bem desenhado é aquele que é invisível para usuários legítimos, mas se torna um muro intransponível para quem tenta abusar da sua infraestrutura. No final das contas, é sobre garantir que sua API esteja sempre pronta para quem realmente precisa dela.


  • API Key: Chave única de identificação de um cliente de API.
  • Admission Control: Decidir se uma requisição deve ser admitida no sistema.
  • Anycast: Técnica de roteamento onde o tráfego vai para o nó mais próximo (desafio para limites globais).
  • API Management: Suíte de ferramentas para gerenciar, monitorar e limitar APIs.
  • Backoff Exponencial: Estratégia de espera progressivamente maior após falhas.
  • Bandwidth Limiting: Restrição da quantidade de dados (bytes) por segundo.
  • Behavioral Analysis: Uso de IA para detectar anomalias no padrão de uso.
  • Botnet: Rede de computadores infectados usada em ataques DDoS.
  • Browser Fingerprinting: Técnica de identificação de usuários baseada em características do navegador.
  • Burst: Rajada de requisições em curto período.
  • CAPTCHA: Teste para diferenciar humanos de máquinas em comportamentos suspeitos.
  • Cascading Failure: Quando a falha de um serviço causa a queda de outros via sobrecarga.
  • Circuit Breaker: Padrão que interrompe chamadas a um serviço instável para evitar falha em cascata.
  • Cold Boot: Lentidão inicial de um sistema de limites logo após o reinício.
  • Cold Cache: Ver "Cold Boot".
  • DDoS: Distributed Denial of Service, ataque que sobrecarrega com requisições massivas.
  • Dead Letter Queue (DLQ): Fila para mensagens que falharam repetidamente por limites ou erros.
  • Distributed Cache: Armazenamento compartilhado (ex: Redis) usado para coordenar limites.
  • Dormant Tokens: Tokens acumulados em um bucket durante períodos de inatividade.
  • Edge Computing: Processamento realizado na borda da rede, perto do usuário.
  • Exponential Backoff: Ver "Backoff Exponencial".
  • Fairness: Princípio de garantir acesso justo aos recursos para todos os usuários.
  • Fixed Window: Algoritmo que divide tempo em janelas discretas rígidas.
  • Fuzzing: Técnica de teste que envia grandes volumes de dados aleatórios (mitigada por limites).
  • GCRA (Generic Cell Rate Algorithm): Algoritmo eficiente para limites baseado em TAT.
  • Graceful Degradation: Capacidade do sistema de continuar funcionando com menos recursos.
  • Greedy Client: Cliente que tenta consumir o máximo de recursos possível.
  • Hard Limit: Limite rígido que bloqueia a requisição imediatamente (429).
  • Header Injection: Ataque onde headers de IP são alterados para burlar o limite.
  • Idempotência: Garantia de que repetir uma mesma operação tem o mesmo efeito final.
  • IP Rotation: Técnica de ataque que muda de IP para evitar rate limits.
  • Jitter: Aleatoriedade adicionada ao tempo de espera para evitar sincronização de retentativas.
  • Key-Value Store: Banco de dados simples usado para contadores de rate limit (ex: Redis).
  • Leaky Bucket: Algoritmo que suaviza tráfego a uma taxa constante de saída.
  • Load Balancer: Distribuidor de tráfego que muitas vezes implementa o limite inicial.
  • Load Shedding: Descarte de requisições baseado no estado de saúde do servidor (CPU/RAM).
  • Lua Scripting: Linguagem usada para executar operações atômicas dentro do Redis.
  • Monitoring: Acompanhamento em tempo real da saúde e eficácia dos limites.
  • Multi-tenancy: Arquitetura onde um sistema serve múltiplos clientes independentes.
  • Negative Acknowledgement: Resposta de falha explícita por exceder limites.
  • Negociação de Taxa: Processo entre cliente e servidor para definir limites dinâmicos.
  • Overhead: Custo adicional de processamento introduzido pelo rate limiter.
  • Priority Queue: Fila que processa requisições VIP antes das normais em sobrecarga.
  • Proof-of-Work (PoW): Exigência de processamento computacional para mitigar spam/ataques.
  • Proxy Server: Intermediário que pode ser usado para ataques de rotação de IP.
  • Quota: A quantidade total de recursos ou requisições permitida para um usuário.
  • Rate Limit Reset: O momento em que o contador de requisições volta a zero.
  • Redis-Cell: Módulo do Redis que implementa o algoritmo GCRA nativamente.
  • Retry Storm: Fenômeno catastrófico onde clientes tentam se reconectar simultaneamente após falhas.
  • Scraper: Script automatizado que extrai dados de APIs ou sites.
  • Secondary Limits: Camadas adicionais de proteção contra abusos de curto prazo.
  • Shaping: Ver "Traffic Shaping".
  • Short-circuiting: Encerrar a requisição o mais cedo possível para economizar recursos.
  • Sidecar Pattern: Processo auxiliar que cuida de infraestrutura (limites, logs).
  • Sliding Window: Algoritmo com janela de tempo contínua móvel.
  • Soft Limit: Limite que avisa o usuário mas não bloqueia a requisição imediatamente.
  • Spike: Aumento repentino e massivo de tráfego.
  • TAT (Theoretical Arrival Time): Conceito central do GCRA para prever a próxima requisição permitida.
  • Throughput: Quantidade de trabalho ou requisições processadas por unidade de tempo.
  • Throttling: Controle de velocidade que atrasa ou limita o fluxo de requisições.
  • Token Bucket: Algoritmo que permite bursts controlados consumindo créditos acumulados.
  • Traffic Shaping: Manipulação do fluxo de dados para que ele obedeça a determinados critérios.
  • User Agent: String de identificação do software do cliente (muitas vezes detectada em abusos).
  • Virtual IP: IP usado por atacantes para simular múltiplos usuários.
  • Waterfall Effect: Quando a falha de um limite causa sobrecarga em cascata em outros sistemas.
  • WAF (Web Application Firewall): Camada de segurança que muitas vezes implementa rate limiting na borda.
  • Wait Time: Tempo que um cliente deve esperar antes de tentar novamente (Retry-After).
  • X-Forwarded-For: Header HTTP usado para identificar o IP original do cliente atrás de um proxy.
  • Zero-Trust: Modelo de segurança que não confia em nenhum cliente por padrão.

21. Conclusão Final e Próximos Passos

O rate limiting não é apenas uma questão técnica; é uma questão de resiliência de negócio. Ter um sistema de limites robusto permite que você durma tranquilo, sabendo que um erro de loop no código de um cliente não trará sua empresa abaixo.

Próximos passos recomendados:

  1. Audite seus endpoints: Identifique quais são os mais caros em termos de CPU/Banco e aplique limites rigorosos.
  2. Implemente Observabilidade: Você deve ser capaz de ver quem está sendo limitado em tempo real no Grafana.
  3. Pense na Experiência do Desenvolvedor: Sempre forneça headers claros e documentação sobre seus limites.

22. Apêndice B: Referências e Leituras Recomendadas

Artigos e Documentação

Livros

  • Kleppmann, M. (2017). Designing Data-Intensive Applications. O'Reilly. (Indispensável para entender sistemas distribuídos).
  • Newman, S. (2015). Building Microservices. O'Reilly. (Foca em padrões de resiliência e comunicação).
  • Adkins, H., et al. (2020). Building Secure and Reliable Systems. O'Reilly. (Trata de Load Shedding e defesa contra abusos).

16. FAQ: Perguntas Frequentes sobre Rate Limiting

1. Qual o melhor algoritmo para uma API REST simples? Para a maioria das APIs, o Token Bucket ou Sliding Window Counter oferece o melhor equilíbrio entre flexibilidade para bursts e proteção de longo prazo.

2. IP Rate Limiting é seguro? Não totalmente. Um atacante pode rotacionar IPs ou esconder-se atrás de uma VPN. Sempre que possível, combine IP com autenticação (API Key ou User ID).

3. O que é o erro HTTP 429? É o status "Too Many Requests". Ele deve ser retornado sempre que um cliente excede seus limites permitidos.

4. Como lidar com clientes que ignoram o rate limit? Se um cliente continua martelando sua API mesmo recebendo 429, você pode escalar a punição banindo o IP temporariamente no firewall (WAF) ou exigindo um desafio CAPTCHA.

5. O rate limiting deve ser síncrono ou assíncrono? Para a melhor precisão (Consistência), ele deve ser síncrono. No entanto, para latência ultra-baixa em sistemas globais, muitas vezes é assíncrono ou híbrido.

6. Rate Limiting é o mesmo que Throttling? Na prática, são usados como sinônimos. Tecnicamente, Throttling é o ato de atrasar a resposta, enquanto Rate Limiting é o ato de limitar a quantidade.

7. Onde devo colocar meu Rate Limiter? O mais perto possível do usuário (na Borda/CDN ou API Gateway) para evitar que o tráfego indesejado chegue à sua infraestrutura principal.

8. Posso ter limites diferentes para GET e POST? Sim, e é altamente recomendado. Operações de escrita (POST/PUT) costumam ser mais caras para o banco de dados e devem ter limites mais rigorosos.

9. O que acontece se meu Redis de Rate Limit cair? Sua aplicação deve estar preparada para "falhar aberto" (permitir tudo) ou usar um limite local de emergência para manter a disponibilidade.

11. Como o rate limiting impacta o SEO? Se o seu bot de busca (Googlebot) bater no limite e receber muitos 429s, ele pode reduzir a frequência de indexação do seu site ou até mesmo penalizá-lo. Sempre crie uma exceção de rate limit para "Allowlisted IPs" de buscadores conhecidos.

12. O que é 'Hydration' de Cache em Rate Limiters? É o processo de pré-carregar os limites de usuários conhecidos na memória RAM (ou Redis) logo após um restart para evitar o "Cold Boot" do sistema de limites.

13. Posso usar rate limiting para proteger contra Injeção de SQL? Não diretamente, mas ele reduz a velocidade com que um atacante pode tentar explorar a vulnerabilidade através de ferramentas automatizadas (fuzzers).

14. Qual a diferença entre Hard e Soft Limits? O Hard Limit bloqueia (429). O Soft Limit apenas marca a requisição com um header de aviso ou envia um alerta para o time de suporte, sem interromper o usuário.

15. Como testar um Rate Limiter? Use ferramentas de teste de carga como JMeter, Locust ou o k6. Verifique se o sistema bloqueia exatamente no contador esperado e se os headers de reset estão corretos.

16. O que é 'Retry-After' e por que ele é vital? É um header HTTP que diz ao cliente exatamente quantos segundos ele deve esperar antes de tentar novamente. Sem ele, os clientes tendem a adivinhar, o que causa re-tentativas inúteis.

17. Posso limitar por tamanho de Payload? Sim! O "Rate Limiting de Banda" limita a quantidade de bytes transferidos por segundo, protegendo contra abusos de upload/download massivos.

18. O que é 'Negative Acknowledgement' no contexto de limites? É quando o servidor informa que a requisição não foi processada devido a limites, permitindo que o cliente decida se deve descartar a tarefa ou movê-la para uma fila de espera.

19. Como o WebSockets lida com Rate Limiting? Como o WebSocket é uma conexão persistente, o limite geralmente é aplicado na abertura da conexão e no número de mensagens enviadas por segundo dentro do túnel.

20. O rate limiting deve ser aplicado em APIs internas? Sim. Em arquiteturas de microserviços grandes, um bug em um serviço interno pode causar uma falha em cascata ("Cascading Failure"). Limites internos evitam que um serviço "mate" o outro.

Este artigo foi desenvolvido com base em rigorosas práticas de engenharia de software e segurança de APIs. Mantenha seus limites sempre atualizados com a evolução do seu tráfego.

Imagem de tecnologia relacionada ao artigo rate-limiting-throttling-apis