rochasolutions
Back-end

Rate Limit de API: Como Implementar sem Travar Usuário Real

Danilo Rocha6 min de leitura

O que é rate limit de API

Rate limit de API é o mecanismo que limita quantas requisições um cliente pode fazer dentro de um intervalo de tempo. Sem ele, um único cliente, seja um script com bug, uma integração mal configurada ou um ataque de força bruta, consome a mesma fila, o mesmo banco e a mesma CPU que atendem todos os outros usuários da API.

O efeito não fica isolado no cliente problemático. Se o banco de dados atinge o limite de conexões por causa de um consumidor único, toda requisição legítima que chega naquele momento espera na mesma fila ou recebe erro. Rate limit existe para transformar um problema de um cliente específico em uma resposta contida, em vez de uma indisponibilidade geral.

Por que uma API sem limite de taxa quebra sob carga real

Uma API sem rate limit trata todo cliente como se tivesse acesso exclusivo aos recursos do servidor. Na prática, banco de dados, memória e capacidade de processamento são compartilhados entre todos os consumidores ao mesmo tempo.

Suponha uma API que atende cem clientes diferentes e um deles, por erro de implementação, dispara uma requisição por segundo em loop infinito. Sem limite, esse cliente consegue consumir uma fração desproporcional da capacidade total, e o tempo de resposta sobe para todo mundo, não só para quem causou o problema. Esse é o cenário mais comum de indisponibilidade que rate limit evita: não o ataque deliberado, mas o bug de integração que ninguém notou a tempo.

Quais algoritmos de rate limiting usar

Os três algoritmos mais usados resolvem o mesmo problema com trade-offs diferentes entre simplicidade, precisão e rajada permitida.

Janela fixa conta requisições dentro de um intervalo fechado, como "cem por minuto, de 00 a 60 segundos". É o mais simples de implementar, mas tem uma falha conhecida: um cliente pode disparar cem requisições no último segundo de uma janela e outras cem no primeiro segundo da próxima, dobrando o limite pretendido num intervalo de dois segundos reais.

Janela deslizante corrige essa falha ao considerar o intervalo móvel dos últimos sessenta segundos a partir do instante atual, não de um relógio fixo. É mais precisa, ao custo de guardar o timestamp de cada requisição, o que consome mais memória do que um contador simples.

Token bucket mantém um balde com um número máximo de tokens, que se esvazia a cada requisição e se repõe a uma taxa constante. Ele permite uma rajada controlada até o limite do balde, depois força o cliente a esperar a reposição. É a escolha mais comum para APIs públicas porque tolera picos legítimos de uso sem penalizar o cliente que normalmente fica bem abaixo do limite.

Onde guardar o contador de requisições

O contador de rate limit precisa ficar em algum lugar que todas as instâncias da API consigam ler e escrever ao mesmo tempo, senão cada instância aplica um limite independente e o limite real vira o dobro ou o triplo do configurado.

Memória local funciona apenas se a API roda numa única instância, o que raramente é o caso em produção. Redis, com sua estrutura de dados INCR e expiração automática por chave, é a escolha padrão para contador compartilhado entre instâncias: cada requisição incrementa um contador com uma chave por cliente e por janela de tempo, e o Redis expira a chave sozinho quando a janela termina. O custo é uma chamada de rede extra por requisição, ainda assim muito mais barata do que deixar o banco principal absorver o excesso de tráfego.

Como implementar rate limit numa API que já está em produção

Aplicar limite de taxa em todos os endpoints de uma vez, numa API que já tem clientes ativos, corre o risco de bloquear tráfego legítimo que ninguém previu.

  1. Meça o tráfego atual por cliente antes de aplicar qualquer limite. Sem esse número, o limite escolhido é um chute.
  2. Escolha o endpoint que mais pesa no banco ou na CPU e aplique o rate limit só nele primeiro.
  3. Defina o limite acima do uso normal observado, com margem, e não do uso ideal que você gostaria que existisse.
  4. Retorne 429 Too Many Requests com o header Retry-After informando quando o cliente pode tentar de novo, seguindo a mesma lógica de código de status coerente usada no resto da API.
  5. Acompanhe a métrica de quantos clientes atingem o limite depois do deploy. Se for um número alto e inesperado, o limite está calibrado errado, não o cliente.
  6. Expanda para os demais endpoints só depois de validar o primeiro por alguns dias.

Como responder ao cliente que excede o limite

O cliente que excede o rate limit precisa receber informação suficiente para se corrigir sozinho, sem abrir chamado de suporte. O código 429 sinaliza claramente que o problema é de volume, não de autenticação ou de dado inválido.

Os headers X-RateLimit-Limit, X-RateLimit-Remaining e Retry-After complementam a resposta: o primeiro informa o limite total da janela, o segundo quantas requisições ainda restam, e o terceiro quantos segundos esperar antes da próxima tentativa. Um cliente bem implementado lê esses headers e ajusta o próprio ritmo de chamadas automaticamente, sem depender de alguém lendo a documentação.

Rate limit não é uma penalidade contra o cliente, é uma proteção para que o comportamento de um não afete todos os demais que compartilham a mesma API. A implementação certa é a que impede o abuso sem exigir que quem usa a API corretamente perceba qualquer diferença no dia a dia.

Se sua API já sofreu instabilidade por causa de um cliente específico ou de um pico de tráfego sem controle, fale com a gente para desenhar o rate limit certo para o seu caso.