Sem um controle de requisições eficaz, uma única entidade – seja um usuário descuidado ou um bot malicioso – pode facilmente sobrecarregar sua API com milhares de chamadas por segundo. Isso não apenas compromete a performance para todos os usuários legítimos, mas também eleva drasticamente seus custos de infraestrutura. A limitação de taxas (rate limiting) surge como uma defesa crucial, estabelecendo um limite de quantas requisições um cliente pode realizar dentro de um período específico.
Por Que Limitar as Requisições da Sua API?
- Prevenir Abusos: Bloqueia tentativas de login por força bruta, spam e a raspagem massiva de dados, salvaguardando a segurança e a integridade da sua plataforma.
- Proteger Recursos do Servidor: Garante que um único usuário ou aplicação não monopolize a capacidade do servidor, mantendo a API responsiva para todos.
- Garantir Acesso Justo: Promove uma distribuição equitativa do acesso à API entre todos os consumidores, evitando que alguns poucos sobrecarreguem o sistema.
- Controlar Custos Operacionais: Limita a execução de operações caras, como inferência de IA, consultas complexas ao banco de dados ou processamento intensivo, otimizando despesas de infraestrutura.
- Conformidade com SLAs: Permite o cumprimento de acordos de nível de serviço e a aplicação de modelos de precificação baseados em tiers de uso, diferenciando usuários gratuitos de clientes premium.
Algoritmos Comuns de Limitação de Taxas
1. Janela Fixa (Fixed Window)
Este é o método mais simples. Ele conta o número de requisições dentro de intervalos de tempo pré-definidos e fixos (por exemplo, por minuto). Uma vez que o contador atinge o limite, todas as requisições subsequentes são rejeitadas até o início da próxima janela. Sua facilidade de implementação, porém, vem com uma desvantagem notável.
Janela: 1 minuto | Limite: 100 requisições 12:00:00 - 12:00:59 → Requisição 1...100 ✅ | Requisição 101 ❌ 12:01:00 - 12:01:59 → Contador zera → Requisição 1...100 ✅ ⚠️ Problema: Um usuário pode enviar 100 requisições às 12:00:59 e mais 100 às 12:01:00 — 200 requisições em apenas 2 segundos!
2. Log da Janela Deslizante (Sliding Window Log)
Este algoritmo mantém um registro de carimbo de tempo para cada requisição. Para determinar se uma nova requisição pode ser aceita, ele conta todas as requisições que ocorreram no período N mais recente. Embora ofereça a maior precisão na aplicação do limite, ele é extremamente intensivo em termos de memória, pois precisa armazenar o histórico de todas as requisições.
3. Contador de Janela Deslizante (Sliding Window Counter)
Uma abordagem mais eficiente, o Contador de Janela Deslizante combina a simplicidade da Janela Fixa com a precisão da Janela Deslizante Log. Ele usa uma média ponderada das contagens da janela atual e da janela anterior para estimar o número de requisições. Este método oferece um bom equilíbrio entre precisão e uso de memória, tornando-o uma escolha popular.
4. Balde de Tokens (Token Bucket) – Recomendado
Considerado um dos algoritmos mais eficientes e flexíveis, o Balde de Tokens simula um "balde" que contém um número limitado de tokens. A cada requisição, um token é consumido. Tokens são adicionados ao balde a uma taxa fixa. Se o balde estiver vazio, as requisições são rejeitadas. Sua principal vantagem é permitir pequenas "rajadas" de tráfego, enquanto ainda impõe uma taxa média de requisições sustentável, o que o torna ideal para APIs com padrões de uso variáveis.
Capacidade do balde: 10 tokens
Taxa de recarga: 1 token/segundo
Segundo 0: Balde tem 10 tokens
→ Usuário envia 5 requisições → 5 tokens consumidos → 5 restantes
Segundo 1: 1 token adicionado → 6 tokens
→ Usuário envia 1 requisição → 5 restantes
Segundo 5: 4 tokens adicionados → 9 tokens
→ Usuário envia 9 requisições em rajada → 0 restantes
Segundo 6: 1 token adicionado → 1 token
→ Usuário pode fazer 1 requisição
Implementação Distribuída com Redis
import Redis from 'ioredis';
const redis = new Redis();
async function rateLimiter(req, res, next) {
const key = `rate:${req.ip}`;
const limit = 100; // requisições
const windowMs = 60 * 1000; // por minuto
const now = Date.now();
const windowStart = now - windowMs;
// Atomic Redis operations
const pipeline = redis.pipeline();
pipeline.zremrangebyscore(key, 0, windowStart); // Remove old entries
pipeline.zadd(key, now, `${now}-${Math.random()}`); // Add current request
pipeline.zcard(key); // Count requests in window
pipeline.expire(key, 60); // Auto-cleanup
const results = await pipeline.exec();
const requestCount = results[2][1];
// Set rate limit headers
res.set({
'X-RateLimit-Limit': limit,
'X-RateLimit-Remaining': Math.max(0, limit - requestCount),
'X-RateLimit-Reset': Math.ceil((now + windowMs) / 1000),
});
if (requestCount > limit) {
res.set('Retry-After', '60');
return res.status(429).json({
error: 'Muitas Requisições',
message: 'Limite de requisições excedido. Por favor, tente novamente mais tarde.',
retryAfter: 60,
});
}
next();
}
app.use('/api/', rateLimiter);
Cabeçalhos Padrão para Respostas de Limite de Requisições
HTTP/1.1 200 OK
X-RateLimit-Limit: 100 // Máximo de requisições por janela
X-RateLimit-Remaining: 73 // Requisições restantes
X-RateLimit-Reset: 1720396800 // Timestamp Unix de quando a janela será resetada
HTTP/1.1 429 Muitas Requisições
Retry-After: 60 // Segundos até que o cliente possa tentar novamente
Content-Type: application/json
{
"error": "Muitas Requisições",
"retryAfter": 60
}
Melhores Práticas para Implementação de Rate Limiting
- Limitar por chave de API ou IP: Para usuários autenticados, use a chave de API. Para usuários anônimos, limite por endereço IP. Isso garante um controle granular e protege contra abusos.
- Aplicar limites variados por endpoint: Nem todos os endpoints têm a mesma carga ou sensibilidade. Endpoints de login, por exemplo, exigem limites mais rigorosos do que endpoints de consulta de dados.
- Retornar respostas 429 informativas: Quando o limite é excedido, envie um status HTTP 429 (Too Many Requests) com um corpo de resposta claro e o cabeçalho
Retry-After, indicando quando o cliente pode tentar novamente. - Incluir cabeçalhos de limite de requisições em todas as respostas: Permita que os clientes da sua API monitorem seu uso e se autorregulem, usando cabeçalhos como
X-RateLimit-Limit,X-RateLimit-RemainingeX-RateLimit-Reset. - Utilizar Redis para limitação distribuída: Em arquiteturas de microsserviços ou com múltiplos servidores, o Redis é ideal para gerenciar contadores de limite de taxas de forma centralizada e eficiente.
- Considerar limites em níveis (tiered limits): Ofereça diferentes limites de requisições com base nos planos de assinatura dos usuários (ex: usuários gratuitos com 100/min, usuários premium com 1000/min).
- Não limitar endpoints de verificação de saúde (health checks): Garanta que seus serviços de monitoramento possam acessar os endpoints de saúde da sua API sem restrições, para não prejudicar a detecção de problemas.
Experimente Nossas Ferramentas Gratuitas para Desenvolvedores
Formate e valide suas respostas de API instantaneamente.