Limite de requisições
Algoritmos para limitar o uso de uma API e proteger o serviço contra abuso e sobrecarga.
Para que limitar
Uma API tem capacidade finita: CPU, conexões com o banco, chamadas a serviços externos. Sem nenhum limite, essa capacidade é dividida por ordem de chegada, e quem chega com mais pedidos leva tudo.
| Ameaça | Exemplo |
|---|---|
| Cliente com defeito | Uma integração presa num laço chamando a mesma rota mil vezes por segundo |
| Robôs e raspagem | Alguém copiando o catálogo inteiro, página por página |
| Força bruta | Milhares de tentativas de senha numa rota de login |
| Abuso de custo | Chamadas repetidas a uma rota que usa um serviço pago, como envio de SMS ou um modelo de IA |
| Picos legítimos | Um parceiro que dispara uma carga enorme de uma vez |
O limite de requisições (rate limiting) define quanto cada cliente pode usar num intervalo e recusa o excesso. A resposta padrão é o código 429 Too Many Requests, com a indicação de quando tentar de novo.
Quem é "o cliente"
Antes do algoritmo, a decisão é o que identifica cada cliente:
| Identificador | Uso | Cuidado |
|---|---|---|
| Chave de API ou usuário autenticado | O mais justo e preciso | Só existe depois da autenticação |
| Endereço IP | Rotas públicas, como login e cadastro | Muitos usuários atrás do mesmo IP (empresas, operadoras móveis); o IP real só vem confiável se o proxy for seu |
| Combinação | Login: por conta e por IP | Mais chaves para contar |
Os algoritmos
Janela fixa
O mais simples: um contador por cliente e por intervalo, como "pedidos do cliente 42 no minuto 14:05". Quando o minuto vira, o contador recomeça.
O problema está na virada. Um cliente pode usar o limite inteiro no fim de uma janela e o limite inteiro no começo da seguinte. Testamos com um limite de 10 pedidos por segundo, guardado no Redis: 10 pedidos aos 0,9 segundo e 10 aos 0,05 do segundo seguinte. Os 20 foram aceitos, num intervalo de 0,11 segundo, o dobro do limite.
Janela deslizante
Conta os pedidos dos últimos N segundos a partir de agora, e não do início do minuto. Elimina o problema da virada. A versão exata guarda o horário de cada pedido; a versão aproximada combina o contador da janela atual com uma fração da anterior, com memória fixa.
Balde de fichas
Cada cliente tem um balde com uma capacidade de fichas. Cada pedido gasta uma ficha. O balde é reabastecido num ritmo constante, até encher. Sem fichas, o pedido é recusado.
capacidade 10, reposição de 5 fichas por segundo
t = 0,0 s balde cheio (10) → rajada de 20 pedidos: 10 aceitos, 10 recusados
t = 1,0 s balde com 5 → 10 pedidos: 5 aceitos, 5 recusadosO balde permite rajadas curtas, até a capacidade, mas limita o ritmo médio. É o comportamento que a maioria das APIs quer: um cliente que carrega uma tela com 8 chamadas de uma vez não deve ser punido, mas não pode manter esse ritmo para sempre. Foi esse o algoritmo implementado e testado nas cinco linguagens, com o resultado exato do diagrama acima.
| Algoritmo | Rajadas | Memória por cliente | Precisão |
|---|---|---|---|
| Janela fixa | Até o dobro do limite, na virada | Um contador | Baixa |
| Janela deslizante exata | Não | Um registro por pedido | Alta |
| Janela deslizante aproximada | Não | Dois contadores | Boa |
| Balde de fichas | Até a capacidade, por desenho | Dois valores | Alta |
O problema das várias instâncias
Com a aplicação em várias cópias, como no tópico de escalabilidade, o contador precisa ser compartilhado. Um limite guardado na memória de cada instância é um limite por instância.
Testamos com duas cópias de um servidor atrás de um Nginx, cada uma com um limite de 10 pedidos por minuto na própria memória. De 30 pedidos do mesmo cliente, 20 foram aceitos: 10 por instância. Com dez instâncias, o limite efetivo seria dez vezes o configurado, e mudaria a cada escala automática.
A solução é guardar a contagem num lugar compartilhado, quase sempre o Redis.
Conferir e depois somar não funciona
A implementação mais intuitiva no Redis lê o contador, confere se está abaixo do limite e grava o novo valor. Com pedidos simultâneos, todos leem o mesmo valor antes de qualquer um gravar.
Testamos com 20 pedidos simultâneos e um limite de 10:
| Implementação | Aceitos |
|---|---|
GET, conferir, SET | 20 |
INCR atômico, conferindo o valor devolvido | 10 |
É a mesma lição do tópico de transações e do de idempotência: conferir e agir precisam ser uma única operação atômica. No Redis, isso significa um comando atômico como INCR ou um script Lua, que o Redis executa sem intercalar com outros comandos.
Por que isso importa quando a IA escreve o código
Um assistente que acrescenta limite de requisições costuma escolher o caminho mais curto:
- Um contador num mapa em memória, que vira um limite por instância.
- Janela fixa, com o dobro do limite na virada.
GETeSETseparados no Redis, que deixam passar rajadas simultâneas.- Identificação pelo IP lido de
X-Forwarded-Forsem conferir se veio do proxy, permitindo que qualquer um troque de "identidade" a cada pedido. - Resposta
429sem dizer quando tentar de novo, e clientes que tentam de novo na hora.
O próximo nível compara onde aplicar o limite, quais valores escolher e como comunicar a recusa.
Prompts para aprofundar
Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.
Limite de requisições em cinco minutos
Explique em no máximo cinco minutos de leitura o que é limite de requisições numa API, para alguém que nunca precisou proteger um serviço contra excesso de uso. Cubra só o essencial: por que limitar, como identificar cada cliente, a diferença entre janela fixa e balde de fichas, e por que a contagem precisa ser compartilhada entre as instâncias. No final, me faça três perguntas curtas para eu verificar se entendi, e corrija as minhas respostas.
Os algoritmos de limite
Quero entender os algoritmos de limite de requisições. Aja como um mentor. Explique, um de cada vez, com uma linha do tempo de pedidos: 1. Janela fixa, e o problema da virada. 2. Janela deslizante exata. 3. Janela deslizante aproximada. 4. Balde de fichas. 5. Balde furado (leaky bucket). Para cada um, me dê uma sequência de pedidos e peça que eu diga quais são aceitos, antes de mostrar a resposta. No final, monte comigo uma tabela comparando rajadas, memória e precisão.
Limites com várias instâncias
Quero entender por que um limite de requisições guardado em memória falha quando a aplicação tem várias instâncias. Explique: 1. O que acontece com um limite em memória atrás de um balanceador com duas, dez e um número variável de instâncias. 2. Por que guardar a contagem no Redis resolve, e por que ler e depois gravar no Redis não resolve. 3. Como um comando atômico ou um script Lua garantem a contagem correta. 4. O problema dos relógios diferentes entre as máquinas, e como o relógio do Redis resolve. Depois me faça três perguntas de cenário e corrija as minhas respostas.
Quem é o cliente
Quero entender como identificar o cliente para aplicar limites de requisições. Explique as opções: chave de API, usuário autenticado, endereço IP e combinações. Para o IP, explique em detalhe: 1. Por que muitos usuários podem compartilhar o mesmo IP. 2. Como o IP real chega atrás de um proxy, e por que o cabeçalho X-Forwarded-For pode ser falsificado. 3. Como configurar a aplicação para confiar nele só quando vier do proxy. Depois me apresente cinco rotas (login, cadastro, busca pública, API de parceiros, envio de SMS) e pergunte como eu identificaria o cliente em cada uma. Corrija as minhas respostas.