Rate limiting implementação parece simples até o primeiro pico de tráfego. A pergunta certa não é "qual biblioteca usar", mas "o que acontece quando o limite estoura". A promessa do rate limiting é proteger sua API de abusos e sobrecarga. A evidência está em APIs públicas que derrubam serviços inteiros quando um cliente faz requisições demais. Este guia entrega um caminho prático, com decisões que você precisa tomar em cada etapa. Você vai sair com uma implementação funcional, mesmo que comece do zero. Pré-requisitos: uma API em qualquer linguagem e um lugar para guardar contadores, que pode ser a própria memória do servidor para testes iniciais.
Passo 1: Escolha o algoritmo de rate limiting
A primeira decisão define o comportamento do seu limite. O fixed window é o mais simples: divide o tempo em janelas fixas, por exemplo 60 segundos, e conta as requisições em cada janela. Se o cliente fizer 100 requisições nos últimos 5 segundos de uma janela e 100 nos primeiros 5 da próxima, ele passou 200 em 10 segundos sem ser bloqueado. O sliding window corrige isso usando uma janela deslizante, mas exige mais processamento. O token bucket é o mais flexível: permite rajadas controladas, como um balde que enche a uma taxa constante e esvazia a cada requisição. Para a maioria dos casos, o fixed window é suficiente e fácil de implementar. A dica: comece com ele, monitore e troque se o comportamento não atender.
Passo 2: Defina onde armazenar o contador
O armazenamento decide se o limite funciona em múltiplas instâncias. Em memória local, cada servidor tem seu próprio contador, o que significa que com duas instâncias o limite efetivo dobra. Para aplicações com uma única instância, isso resolve. Para múltiplas, use o Redis com o comando INCR e EXPIRE, que é atômico e compartilhado. O erro comum aqui é esquecer que a memória local não escala horizontalmente. Se sua API roda em um cluster, o rate limit em memória dá uma falsa sensação de segurança. A alternativa com banco de dados relacional funciona, mas adiciona latência a cada requisição. A decisão depende do seu volume: até algumas dezenas de requisições por segundo, um banco resolve; acima disso, Redis é a escolha natural.
Passo 3: Implemente o middleware de rate limiting
Com algoritmo e armazenamento definidos, o próximo passo é o código. O middleware intercepta cada requisição antes de chegar ao seu endpoint. Para cada requisição, você incrementa o contador da chave, que normalmente é o IP do cliente ou um token de autenticação. Se o contador ultrapassar o limite, retorne HTTP 429 Too Many Requests. Inclua no cabeçalho de resposta o tempo de espera até a próxima janela, com o header Retry-After. A dica: use o IP como chave padrão, mas permita sobrescrever com um identificador de usuário quando houver autenticação, porque vários usuários atrás de um mesmo IP não devem compartilhar o mesmo limite. O erro comum é não incluir um identificador de cliente, o que bloqueia usuários legítimos em redes corporativas.
Passo 4: Configure limites realistas por tipo de cliente
O limite não é um número único para todos. Uma API pública pode permitir 10 requisições por minuto para usuários anônimos e 100 por minuto para usuários autenticados. Um serviço interno pode aguentar 1000 por segundo. O valor certo depende do que sua infraestrutura suporta e do que seus clientes precisam. O erro comum é copiar limites de outros serviços sem testar. Faça um teste de carga simples com uma ferramenta como k6 ou Apache Bench para ver quantas requisições sua API aguenta antes de degradar. A partir desse número, defina o limite com uma margem de segurança, por exemplo, 70% da capacidade observada. A dica: comece com limites generosos e reduza gradualmente, monitorando o impacto. Limites muito baixos geram reclamações; limites altos não protegem nada.
Passo 5: Trate as respostas de erro com clareza
Quando o limite é excedido, a resposta precisa ser mais informativa que um simples 429. Inclua no corpo da resposta quantas requisições ainda são permitidas, quando a janela reinicia e um link para a documentação. Isso reduz a frustração do cliente e evita que ele tente de novo imediatamente. O erro comum é retornar 429 sem explicação, o que leva o cliente a pensar que a API está fora do ar. A dica: use os headers padrão X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset, que são amplamente reconhecidos. Eles ajudam o cliente a se autoajustar sem precisar adivinhar. Se o cliente ignorar os avisos, o bloqueio é o comportamento correto, mas você deve dar a chance de ele entender o motivo.
Passo 6: Teste o rate limiting em cenários reais
Testar rate limiting não é só enviar mais requisições que o limite. É verificar o comportamento no limite, acima dele e na borda da janela. Crie um teste que envie exatamente o limite de requisições e confirme que todas passam. Depois, envie uma a mais e confirme que recebe 429. Por fim, espere a janela reiniciar e verifique se o contador zerou. O erro comum é testar apenas o bloqueio e esquecer de testar a liberação. A dica: automatize esses testes no seu pipeline de CI para garantir que uma mudança futura não quebre o rate limit. Um teste manual na hora da implementação não protege contra regressões. Frameworks como JUnit e pytest têm suporte para esse tipo de teste, mas você pode fazer com um script simples que conta as respostas HTTP.
Passo 7: Monitore e ajuste o rate limiting
Rate limiting não é configurar e esquecer. Métricas como o número de respostas 429, o tempo de resposta médio e a taxa de erro da API mostram se o limite está adequado. Se os 429 aumentam muito, o limite pode estar baixo demais. Se nunca aparecem, o limite pode estar alto demais e não proteger nada. A dica: integre o rate limit ao seu sistema de logs e métricas, como Prometheus ou Grafana. O erro comum é não monitorar e descobrir o problema quando um cliente legítimo é bloqueado em produção. Ajuste os limites com base nos dados observados, não em suposições. Uma mudança de limite deve ser documentada e comunicada aos clientes, porque altera o comportamento da API para eles.
Checklist do que você implementou
- Algoritmo de rate limiting escolhido e documentado
- Armazenamento do contador definido (memória, Redis ou banco)
- Middleware configurado para retornar 429 com headers informativos
- Limites diferenciados por tipo de cliente, se aplicável
- Testes automatizados cobrindo bloqueio e liberação
- Métricas de monitoramento ativas para acompanhar o impacto
Perguntas frequentes sobre rate limiting
Qual a diferença entre rate limiting e throttling?
Rate limiting bloqueia requisições que excedem um limite em um intervalo de tempo. Throttling reduz a velocidade de processamento, mas não bloqueia completamente. Na prática, rate limiting é mais comum em APIs porque é mais simples de implementar e o comportamento é previsível para o cliente.
O que é o header Retry-After?
O header Retry-After indica ao cliente quantos segundos ele deve esperar antes de fazer a próxima requisição. Ele é retornado junto com o status 429. Isso evita que o cliente tente de novo imediatamente e sobrecarregue ainda mais o servidor.
Rate limit por IP é suficiente?
Para APIs públicas, o IP é um bom ponto de partida, mas não é infalível. Usuários atrás de um mesmo IP (como uma rede corporativa) podem ser bloqueados injustamente. Se sua API tem autenticação, use o ID do usuário como chave principal e o IP como fallback.
Como escolher o limite de requisições?
O limite deve ser baseado na capacidade da sua infraestrutura e nas necessidades dos clientes. Faça um teste de carga para descobrir quantas requisições sua API aguenta sem degradar. Defina o limite com uma margem de segurança e ajuste com base no monitoramento.
Rate limiting afeta o desempenho da API?
Sim, mas o impacto é pequeno quando o armazenamento é em memória ou Redis. Cada requisição adiciona uma operação de incremento no contador, que é rápida. O custo é maior quando o contador fica em um banco relacional, porque adiciona latência a cada requisição.
Quando devo usar um rate limit global versus por usuário?
Um limite global protege a API como um todo contra picos de tráfego. Um limite por usuário garante uso justo entre clientes. Para a maioria dos casos, você precisa dos dois: um limite global para evitar sobrecarga e um por usuário para evitar abuso individual.