O que é rate limiting e por que é essencial

Controlar quantas requisições cada cliente pode fazer por unidade de tempo

Rate limiting é o mecanismo que limita a frequência com que um cliente pode chamar uma API em um intervalo de tempo. Sem rate limiting, um único cliente mal-intencionado, um script com bug em loop ou um bot agressivo pode fazer dezenas de milhares de requisições por segundo e tornar a API inoperante para todos os outros usuários. A proteção não é apenas contra ataques — é também contra clientes legítimos com comportamento incorreto (como retry em loop sem exponential backoff) que inadvertidamente sobrecarregam o sistema. Rate limiting é proteção tanto de disponibilidade quanto de equidade no uso dos recursos.

Algoritmos de rate limiting — como cada um funciona

Token bucket, sliding window, fixed window e leaky bucket

Os quatro algoritmos principais são: Fixed Window (conta requisições em janelas fixas de tempo — simples mas vulnerável a burst no limite da janela), Sliding Window (conta requisições nos últimos N segundos de forma contínua — mais preciso, mais custoso), Token Bucket (cada cliente tem um balde de tokens que recarrega a uma taxa fixa; cada requisição consome um token — permite burst controlado), e Leaky Bucket (requisições entram em uma fila e são processadas em taxa constante — garante taxa uniforme mas pode atrasar). Token bucket com sliding window é o mais usado em produção por equilibrar precisão com capacidade de burst para clientes legítimos.

Granularidade — por onde limitar

IP, usuário autenticado, API key, rota, serviço de origem

A granularidade do rate limit define quem compartilha o mesmo limite. Limitar por IP protege contra ataques externos mas pode bloquear usuários legítimos atrás de NAT compartilhado (como empresas onde todos compartilham o mesmo IP). Limitar por usuário autenticado é mais preciso para APIs com autenticação. Por API key é ideal para B2B onde cada cliente tem sua chave. Por rota permite limites diferentes para operações caras versus baratas (POST com processamento pesado tem limite menor que GET de listagem). Em produção, geralmente se combina múltiplas granularidades: global por IP para proteção básica e por usuário autenticado para controle granular.

Rate limiting distribuído com Redis

Como compartilhar contadores entre múltiplas instâncias da aplicação

Em aplicações com múltiplas instâncias, cada servidor não pode manter contadores locais — um cliente poderia fazer 100 requisições para cada instância, burlando um limite de 100 por minuto. A solução padrão é Redis como contador distribuído. O algoritmo de fixed window com Redis usa INCR e EXPIRE: INCR key incrementa o contador atomicamente e EXPIRE define a janela de tempo. Para sliding window mais preciso, Redis Sorted Sets armazenam o timestamp de cada requisição, e a contagem remove timestamps fora da janela. Bibliotecas como rate-limiter-flexible (Node.js) e AspNetCoreRateLimit (.NET) abstraem esse Redis storage.

Headers de rate limit — comunicando os limites ao cliente

RateLimit-Limit, RateLimit-Remaining e RateLimit-Reset

Clientes que consomem APIs precisam saber quando retryar e quanto do limite está disponível. Os headers padronizados (RFC 6585 e draft IETF) são: X-RateLimit-Limit (limite máximo do período), X-RateLimit-Remaining (requisições restantes na janela atual), e X-RateLimit-Reset (timestamp UNIX de quando o limite será reiniciado). O status HTTP correto para requisições rejeitadas por rate limit é 429 (Too Many Requests) com o header Retry-After indicando em quantos segundos o cliente pode tentar novamente. APIs que retornam 429 com Retry-After correto reduzem drasticamente o número de retries agressivos que pioram a situação.

Estratégias de resposta para requisições bloqueadas

Rejeitar, enfileirar ou degradar gracefully

Quando um cliente ultrapassa o limite, há três abordagens: rejeitar imediatamente com 429 (mais simples, protege o servidor mas pode causar erros visíveis ao usuário), enfileirar a requisição para processamento quando o limite liberar (melhor UX mas aumenta memória e latência), e degradar gracefully com resposta parcial ou cacheada (retornar dado mais antigo ou resultado de qualidade reduzida em vez de erro). Para APIs públicas, rejeitar com 429 e Retry-After é o padrão. Para interfaces de usuário interno, degradação graceful com dados em cache é melhor experiência. Para jobs em background, enfileirar com backoff é o comportamento mais correto.

Rate limiting por serviço — proteção em microsserviços

Cada microsserviço deve ter seus próprios limites configurados

Em arquitetura de microsserviços, rate limiting deve existir em múltiplas camadas: no API Gateway (limite por cliente externo antes de chegar aos serviços internos), em cada microsserviço (limite por serviço chamador para evitar que um serviço sobrecarregue outro), e no cliente HTTP de cada serviço (circuit breaker + rate limiting para chamadas a serviços externos como APIs de terceiros). Ferramentas como Kong, AWS API Gateway, NGINX e Envoy Proxy têm rate limiting nativo. Para microsserviços internos, o padrão é implementar no próprio serviço usando Redis compartilhado para contadores distribuídos.

Diferença entre rate limiting e throttling

Termos parecidos com comportamentos distintos

Rate limiting rejeita requisições que excedem o limite — o cliente recebe erro imediato. Throttling desacelera o processamento — o servidor aceita a requisição mas a enfileira ou atrasa a resposta para processar em taxa controlada. Na prática, rate limiting é hard limit (rejeição) e throttling é soft limit (desaceleração). APIs públicas geralmente usam rate limiting para proteger recursos e oferecer planos com limites diferentes (free: 100/hora, paid: 10000/hora). Sistemas internos com SLAs mais flexíveis podem preferir throttling para absorver picos sem rejeitar requisições de serviços próprios.

Evitando falsos positivos — limites que bloqueiam usuários legítimos

Rate limits muito apertados são tão ruins quanto não ter rate limit

Um rate limit mal calibrado bloqueia usuários legítimos e gera suporte desnecessário. Para calibrar corretamente: analise o padrão real de uso antes de definir limites (percentil 99 de requisições por usuário em um dia normal é o piso mínimo do limite), use limites por nível de usuário (usuário gratuito vs premium vs enterprise), implemente whitelist para IPs confiáveis de parceiros e sistemas internos, e monitore a taxa de 429 para detectar falsos positivos. Um limite que gera mais de 0.1% de 429 em tráfego legítimo provavelmente está muito restrito.

Conclusão — rate limiting é proteção e qualidade de serviço

Limites bem definidos protegem todos os usuários igualmente

Rate limiting não é apenas proteção contra abuso — é garantia de qualidade de serviço igual para todos os clientes. Sem ele, um cliente agressivo consome recursos que prejudicam todos os outros. Com rate limits bem calibrados, a API mantém performance previsível mesmo sob pressão, clientes são incentivados a usar de forma eficiente, e o sistema tem uma primeira linha de defesa contra ataques de DDoS em nível de aplicação. Implemente antes do lançamento público — adicionar rate limiting após usuários estarem acostumados com comportamento irrestrito é muito mais difícil. Continue em: Fundamentos obrigatórios antes de produção.

Rate Limiting e Proteção de APIs — Vídeos

Rate Limiting e Segurança de APIs no Instagram

Token Bucket

Algoritmo de rate limiting com balde de tokens que recarrega em taxa fixa — permite burst controlado para picos legítimos.

Sliding Window

Conta requisições nos últimos N segundos de forma contínua — mais preciso que fixed window.

429 Too Many Requests

Status HTTP correto para requisições rejeitadas por rate limit — deve incluir Retry-After.

RateLimit-Remaining

Header HTTP que indica quantas requisições ainda podem ser feitas na janela atual.

Retry-After

Header HTTP que indica em quantos segundos o cliente pode tentar novamente após receber 429.

Throttling

Desacelera o processamento em vez de rejeitar — soft limit que enfileira em vez de retornar erro.

Rate Limiting no X

@bytebytego

Reels — Sistemas e Arquitetura

@bytebytego

ByteByteGo no Facebook

Referências e Leituras Recomendadas

@mjovanovictech

Como testar que sua API é resiliente e segura para produção real

Ver post completo no X →
@mjovanovictech

Implementando padrões de resiliência em .NET Core com exemplos reais

Ver post completo no X →
@mjovanovictech

Vertical Slice Architecture — organizando sistemas para escala

Ver post completo no X →
@mjovanovictech

5 anos com Clean Architecture — lições de sistemas em produção

Ver post completo no X →
@mjovanovictech

Design de APIs resilientes — retry, backoff e idempotência juntos

Ver post completo no X →
@mjovanovictech

Monolito vs Microsserviços — como escolher para cada contexto

Ver post completo no X →

Links Úteis

O que dizem