24 de Junho de 2025
Rate limiting: quando, como e por quê
Como pensar em rate limiting como proteção de capacidade compartilhada, quais estratégias existem e o que realmente importa na prática.
Andrews Ribeiro
Founder & Engineer
5 min Intermediario Sistemas
Trilha
Trilha de system design para entrevistas
Etapa 10 / 19
O problema
Rate limiting aparece em muita conversa como detalhe rápido.
Alguém fala:
- “coloca um limiter na borda”
e parece que o assunto acabou.
Só que a parte importante não é citar a existência do limitador.
É explicar:
- o que ele está protegendo
- para quem o limite vale
- qual comportamento ele cria quando a carga aperta
Sem isso, o sistema corre dois riscos bem comuns:
- um cliente consome capacidade demais e piora a vida dos outros
- o próprio sistema degrada de forma caótica em vez de previsível
Modelo mental
Pense assim:
rate limiting é um contrato de capacidade.
Em português simples, você está dizendo:
- acima de certo ritmo, este cliente vai ter de esperar, falhar ou ser desacelerado
Isso pode servir para coisas diferentes:
- proteger API pública
- reduzir abuso
- distribuir recurso compartilhado
- conter burst
- limitar ações caras, como login, envio de SMS ou geração de relatório
Então a pergunta útil não é:
- “precisa de rate limiting?”
É esta:
qual capacidade eu estou protegendo, para quem, e com qual comportamento quando o limite for atingido?
Quebrando o problema
Onde o rate limiter costuma ficar
O lugar mais comum é perto da entrada do sistema:
- API gateway
- load balancer com regra
- camada HTTP da aplicação
Quanto mais cedo o bloqueio acontece, menos recurso inútil você gasta.
Mas isso não significa que todo limite vive só na borda.
Tem limite que faz mais sentido perto da regra:
- por usuário
- por ação específica
- por recurso caro
- por integração externa
Exemplo:
- limitar requests por API key na borda faz sentido
- limitar “no máximo 3 SMS por hora para o mesmo usuário” já é mais domínio do produto
Algoritmo muda o comportamento
Não precisa decorar fórmula.
Precisa entender como cada opção se comporta.
Fixed window:
- simples
- barato de explicar
- mas cria efeito estranho na virada da janela
O cliente pode mandar muito no fim de um minuto e muito de novo no começo do próximo.
Sliding window:
- suaviza essa borda
- tende a ser mais justo
- mas costuma ser um pouco mais caro de manter
Token bucket:
- enche um balde com tokens ao longo do tempo
- cada request gasta um token
- permite burst controlado
Em entrevista, token bucket costuma ser uma boa resposta porque equilibra clareza e comportamento real.
Rate limiting distribuído quase sempre pede estado compartilhado
Se você tem várias instâncias e cada uma conta localmente, o cliente pode driblar o limite passando por instâncias diferentes.
Por isso, em sistema distribuído, o contador costuma ir para algum lugar compartilhado.
Redis aparece muito aqui porque:
- é rápido
- lida bem com contador e expiração
- permite operação atômica útil para esse caso
Não é obrigatório em todo cenário.
Mas é um desenho comum e fácil de defender.
A chave do limite muda o efeito
Você pode limitar por:
- IP
- usuário
- API key
- tenant
- rota
- combinação de atributos
Cada escolha protege uma coisa diferente.
Por IP ajuda contra burst de origem específica.
Por usuário ajuda a isolar comportamento individual.
Por API key costuma funcionar bem para integrações de terceiros.
Não existe chave universal.
Existe a chave que melhor separa quem divide aquele recurso.
Limitar demais também machuca uso legítimo
Esse é um ponto que muita gente esquece.
Rate limiting ruim não protege só o sistema.
Também pode punir cliente bom.
Se o limite for duro demais, o produto fica com cara de portão travado.
Então a pergunta madura não é só:
- “qual o máximo permitido?”
Também é:
- “qual burst legítimo o uso normal precisa aguentar?”
A resposta ao cliente faz parte do design
Quando o limite estoura, o sistema precisa se comportar de forma compreensível.
Em HTTP, o padrão mais comum é:
429 Too Many Requests
E idealmente com sinal claro sobre:
- quando tentar de novo
- qual política está valendo
Cabeçalhos como Retry-After ajudam.
O importante é:
o limite não deve parecer falha aleatória.
Exemplo simples
Imagine uma API pública de consulta de preço.
Sem rate limiting, um cliente descuidado ou agressivo pode disparar milhares de requests por segundo e piorar a latência para todo mundo.
Uma resposta madura poderia ser:
“Vou limitar por API key na borda porque quero proteger capacidade compartilhada por consumidor. Como preciso permitir burst curto, token bucket faz sentido. Como tenho várias instâncias, guardo contagem em Redis. Quando o limite estourar, devolvo
429com orientação de retry.”
Repare no que essa resposta explica:
- o que está sendo protegido
- para quem o limite vale
- qual algoritmo encaixa
- onde o estado vive
- como o cliente descobre o que aconteceu
Erros comuns
- Tratar rate limiting como detalhe de segurança e esquecer capacidade.
- Contar localmente em cada instância e achar que está protegido.
- Escolher algoritmo só pelo nome, sem explicar o comportamento.
- Bloquear sem resposta clara para o cliente.
- Usar o mesmo limite para tudo.
- Não distinguir burst legítimo de abuso real.
Como um senior pensa
Quem tem mais experiência raramente fala só:
- “coloca rate limiter”
Costuma falar algo mais útil:
“Quero proteger capacidade compartilhada sem punir uso normal. Então vou escolher a chave do limite, o algoritmo e a resposta ao cliente de acordo com quem divide esse recurso e com o burst que o produto precisa tolerar.”
Essa resposta mostra maturidade porque sai do binário “tem ou não tem” e entra no comportamento real do sistema.
Também mostra que rate limiting não é só defesa.
É mecanismo de previsibilidade.
O que o entrevistador quer ver
Em entrevista, rate limiting revela rápido se você pensa em confiabilidade como parte do produto.
O entrevistador normalmente quer ver se você:
- entende o que está protegendo
- diferencia algoritmo por comportamento
- considera distribuição entre instâncias
- lembra que a resposta ao cliente também faz parte do design
Uma resposta forte costuma ter esta forma:
“Eu começo definindo qual recurso compartilhado está sob risco e quem precisa ser isolado. Depois escolho a chave do limite e o algoritmo de acordo com o burst aceitável. Se o sistema é distribuído, guardo a contagem em estado compartilhado. E trato o estouro de limite como comportamento previsto da API, não como erro genérico.”
Rate limiting não é só muro de defesa. É uma forma de deixar a capacidade compartilhada previsível.
O limite bom protege o sistema sem transformar o produto em punição para quem está usando direito.
Resumo rápido
O que vale manter na cabeça
- Rate limiting protege capacidade compartilhada e ajuda a manter fairness entre clientes.
- O algoritmo importa porque muda o comportamento do limite diante de burst, janelas e distribuição entre instâncias.
- Em sistema distribuído, contar localmente em cada instância quase nunca basta.
- A resposta ao cliente também faz parte do design: limite bom não deve parecer falha aleatória.
Checklist de pratica
Use isto ao responder
- Consigo explicar o que muda entre fixed window, sliding window e token bucket sem decorar fórmula?
- Sei dizer onde um rate limiter costuma ficar e quando ele também entra perto da regra de negócio?
- Consigo explicar por que Redis aparece tanto nesse problema?
- Sei o que devolver ao cliente quando o limite estoura?
Você concluiu este artigo
Parte da trilha: Trilha de system design para entrevistas (10/19)
Próximo passo
Load balancing sem caixa preta Próximo passo →Compartilhar esta página
Copie o link manualmente no campo abaixo.