Design clássico · Júnior
Rate limiter
Token bucket, janela deslizante e onde colocar o limitador: cliente, gateway ou serviço.
Resposta curta
Token bucket, janela deslizante e onde colocar o limitador: cliente, gateway ou serviço. Um limitador de taxa decide, para cada requisição, se ela passa ou é recusada. Ele protege o backend contra picos e abusos, e deixa claro para o cliente quanto ele pode consumir.
01 · CONTEXTO
Por que limitar a taxa de requisições
Um limitador de taxa decide, para cada requisição, se ela passa ou é recusada. Ele protege o backend contra picos e abusos, e deixa claro para o cliente quanto ele pode consumir. Em entrevista, o ponto de partida é levantar requisitos: limitar por usuário, por IP ou por chave de API? Qual a regra (quantas requisições por intervalo)? O limitador precisa funcionar com muitos servidores? O que acontece quando ele próprio falha?
A primeira decisão é onde ele roda. No cliente não serve: as requisições podem ser forjadas por quem tem má intenção, então o cliente é um lugar não confiável para impor o limite. No lado do servidor, o limitador pode ser um middleware ou, o mais comum, viver dentro do API gateway, que já fica na frente de todos os serviços.
O cliente é quem origina as requisições, mas não pode ser quem decide o limite: ele é controlado por quem quer abusar.
O gateway recebe todo o tráfego antes dos serviços; é o ponto natural para aplicar a regra de limite.
Os contadores de cada chave precisam de um armazenamento rápido: o gateway consulta e atualiza um cache em memória a cada requisição.
Dentro do limite, a requisição segue ao serviço; acima dele, o gateway responde com o código de excesso de requisições e o serviço nem chega a ser tocado.
02 · ALGORITMOS
Token bucket e leaking bucket
No token bucket, cada chave tem um balde com capacidade pré-definida. Dois parâmetros o descrevem: o tamanho do balde, que é o máximo de tokens que ele comporta, e a taxa de reposição, o número de tokens colocados nele a cada segundo. Cada requisição consome um token; sem token, ela é recusada. O tamanho do balde define quanta rajada é tolerada; a taxa de reposição define o ritmo sustentado.
O leaking bucket é parecido, mas as requisições são processadas a uma taxa fixa. Costuma ser implementado com uma fila FIFO: o que chega entra na fila e sai em ritmo constante. Isso suaviza a saída, ao custo de não deixar a rajada passar rápido.
03 · JANELAS
Janela fixa, log deslizante e contador deslizante
A janela fixa divide o tempo em intervalos de tamanho fixo e mantém um contador por intervalo. É simples e barata, mas tem um defeito conhecido: uma rajada na borda entre duas janelas pode deixar passar mais requisições do que a cota permite, porque o cliente esgota uma janela no fim e a seguinte logo no começo.
O log deslizante guarda o timestamp de cada requisição e descarta os mais antigos que o início da janela atual; resolve a borda, mas consome muita memória, porque até as requisições recusadas podem ter o timestamp guardado. O contador deslizante é um híbrido entre janela fixa e log: suaviza os picos usando a taxa da janela anterior como referência, com memória bem menor.
| Algoritmo | Ponto forte | Ponto fraco |
|---|---|---|
| Token bucket | Aceita rajadas controladas pelo tamanho do balde | Dois parâmetros para calibrar |
| Leaking bucket | Saída em taxa fixa, via fila FIFO | Rajadas esperam na fila |
| Janela fixa | Um contador por janela | Rajada na borda passa da cota |
| Log deslizante | Janela precisa | Memória alta, pois guarda timestamps |
| Contador deslizante | Suaviza picos com pouca memória | Estimativa baseada na janela anterior |
04 · DISTRIBUIÇÃO
Vários gateways, um contador compartilhado
Com várias instâncias de gateway atrás de um balanceador de carga, contadores locais não bastam: cada instância veria só parte do tráfego da chave. O contador vai para um cache compartilhado. O Redis oferece dois comandos que cobrem o caso: INCR aumenta o contador armazenado e EXPIRE define um tempo de vida, após o qual o contador é apagado sozinho.
O problema aparece sob concorrência: se duas instâncias leem o contador, incrementam e gravam de volta sem olhar uma para a outra, uma contagem se perde e o limite é ultrapassado. Locks são a solução mais óbvia; a alternativa é executar a decisão inteira em um script Lua, que é atômico, tornando a decisão livre dessa condição de corrida.
O balanceador espalha as requisições de uma mesma chave entre as instâncias de gateway; nenhuma delas vê o tráfego completo.
Ambas as instâncias passam a consultar o mesmo cache; o contador deixa de ser local e vira estado compartilhado.
Se as duas instâncias leem o mesmo valor e cada uma grava a própria soma, um incremento se perde e passa requisição acima do limite.
Com a leitura, a conta e a gravação dentro de um único script atômico no cache, a decisão deixa de ter janela para corrida.
05 · FALHAS E RESPOSTA
Quando o limitador cai e o que o cliente recebe
O armazenamento dos contadores também falha, e é preciso decidir de antemão o que fazer. Fail-open deixa o tráfego passar: o custo é perder temporariamente a proteção. Fail-closed recusa: a justificativa é que breves períodos de requisições rejeitadas são preferíveis a um colapso em cascata. Não existe resposta única; depende do que o limite protege. Pense nisso junto com padrões de disponibilidade.
O cache de contadores fica indisponível: os gateways não conseguem mais consultar nem atualizar o estado do limite.
Em fail-open, os gateways deixam tudo passar e o serviço fica exposto a picos sem proteção; em fail-closed, recusam e preservam o serviço ao custo de rejeitar tráfego legítimo.
Quando a requisição é recusada, a API devolve o código HTTP 429 (muitas requisições). Cabeçalhos informam o limite, o restante da cota e quantos segundos esperar antes de tentar de novo, e o cliente bem-comportado respeita esse tempo. Para crescer além de um nó de Redis, uma opção é fazer hash do identificador do usuário para escolher o shard que guarda os dados de limite dele.
Perguntas frequentes
O que é Rate limiter?
Token bucket, janela deslizante e onde colocar o limitador: cliente, gateway ou serviço.
O que o design de Rate limiter cobre?
Ele está organizado nestas seções: Por que limitar a taxa de requisições, Token bucket e leaking bucket, Janela fixa, log deslizante e contador deslizante, Vários gateways, um contador compartilhado e Quando o limitador cai e o que o cliente recebe.
Quanto tempo leva Rate limiter e qual é o nível?
Leva cerca de 14 minutos para ler e tem nível Júnior.
Agora projete você mesmo
Rode este caso como uma entrevista na escola de System Design: você toma as decisões, o tutor as questiona e você vê a nota do seu desenho.