Como Funciona o Rate Limiting - Controle de Acesso para Proteger APIs

14 min leitura | 2025.12.13

O que é Rate Limiting

Rate Limiting (Limitação de Taxa) é um mecanismo que limita o número de requisições de API em um determinado período. Mantém a estabilidade do serviço e protege o sistema contra uso malicioso ou acessos excessivos causados por bugs.

Por que é necessário: Se requisições forem aceitas sem limite, um único usuário pode consumir todos os recursos do sistema, ou ataques DDoS podem derrubar o serviço.

Objetivos do Rate Limiting

ObjetivoDescrição
Proteção do serviçoPrevenir quedas por sobrecarga
Garantir equidadeDistribuir recursos de forma justa para todos os usuários
Prevenção de abusoImpedir scraping, ataques de força bruta
Gestão de custosGarantir previsibilidade nos custos de infraestrutura

Principais Algoritmos

1. Janela Fixa (Fixed Window)

Reseta o contador a cada janela de tempo fixa.

Configuração: Janela de 1 minuto (00:00~00:59), limite de 100 requisições/minuto

HorárioRequisiçõesResultado
00:00-00:3090OK
00:30-00:5910OK (total 100)
01:00Contador reseta
01:00-01:30100OK

Problema: Na fronteira da janela, momentaneamente é possível o dobro de requisições

HorárioRequisiçõesProblema
00:59100OK
01:00100OK
-> 200 requisições em 2 segundos!

2. Log de Janela Deslizante (Sliding Window Log)

Registra o timestamp de cada requisição e conta as requisições nos últimos N segundos.

Hora atual: 01:00:30, Janela: últimos 60 segundos (00:00:30~01:00:30)

TimestampStatus
00:00:25Fora da janela (removido)
00:00:35OK Válido
00:00:50OK Válido
01:00:10OK Válido

Vantagem: Rate limiting preciso Desvantagem: Alto uso de memória

3. Contador de Janela Deslizante (Sliding Window Counter)

Versão melhorada da janela fixa. Calcula ponderando os contadores das janelas anterior e atual.

JanelaNúmero de requisições
Anterior (00:00-00:59)80
Atual (01:00-01:59)30
Hora atual01:00:20 (33% decorrido)

Cálculo: Requisições estimadas = 80 × 0.67 + 30 = 83.6

4. Token Bucket (Balde de Tokens)

Tokens são adicionados ao balde a uma taxa constante, e cada requisição consome um token.

Configuração: Capacidade do balde 10 tokens, taxa de reposição 1 token/segundo

EstadoTokensObservação
Estado inicial10/10Cheio
Após 5 requisições5/105 tokens consumidos
Após 3 segundos8/103 tokens repostos

Burst: Atualmente 8 requisições possíveis

Vantagens: Suporta bursts, eficiente em memória

5. Leaky Bucket (Balde Furado)

Requisições são processadas do balde a uma taxa constante.

flowchart LR
    In["Entrada<br/>(variável)"] --> Bucket["Balde<br/>(fila)"] --> Out["Saída<br/>(taxa fixa)"]

Vantagem: Taxa de saída estável Desvantagem: Não lida bem com bursts

Padrões de Implementação

Headers de Resposta

HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1640000000

Resposta de Limite Excedido

HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json

{
  "error": "rate_limit_exceeded",
  "message": "Limite de taxa excedido. Tente novamente em 30 segundos.",
  "retry_after": 30
}

Exemplo de Implementação com Redis

async function checkRateLimit(userId, limit, windowSec) {
  const key = `ratelimit:${userId}`;
  const current = await redis.incr(key);

  if (current === 1) {
    await redis.expire(key, windowSec);
  }

  if (current > limit) {
    const ttl = await redis.ttl(key);
    return { allowed: false, retryAfter: ttl };
  }

  return { allowed: true, remaining: limit - current };
}

Granularidade do Limite

Baseado em Usuário

UsuárioLimite
Usuário A100 requisições/minuto
Usuário B100 requisições/minuto

Baseado em Endereço IP

Endereço IPLimite
192.168.1.1100 requisições/minuto
192.168.1.2100 requisições/minuto

Baseado em Endpoint

EndpointLimiteObservação
GET /api/users100 requisições/minuto
POST /api/users10 requisições/minutoCriação é mais restrita

Hierárquico

PlanoLimite
Free tier100 requisições/dia
Pro tier10.000 requisições/dia
EnterpriseIlimitado

Considerações em Sistemas Distribuídos

Centralizado

flowchart LR
    S1["Servidor 1"] --> Redis["Redis<br/>(contador compartilhado)"]
    S2["Servidor 2"] --> Redis
    S3["Servidor 3"] --> Redis

Vantagem: Preciso Desvantagem: Latência para o Redis

Cache Local + Sincronização

flowchart LR
    S1["Servidor 1<br/>Contador local"] <-->|Sincronização periódica| S2["Servidor 2<br/>Contador local"]

Vantagem: Baixa latência Desvantagem: Tolera pequenas ultrapassagens

Tratamento no Lado do Cliente

Exponential Backoff

async function fetchWithRetry(url, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url);

    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
      await sleep(retryAfter * 1000);
      continue;
    }

    return response;
  }
  throw new Error('Rate limit exceeded after retries');
}

Resumo

Rate limiting é um mecanismo importante para garantir a estabilidade e equidade da API. Escolhendo o algoritmo adequado ao caso de uso, como token bucket ou sliding window, e configurando limites com a granularidade apropriada, é possível proteger o serviço enquanto proporciona uma boa experiência ao usuário.

← Voltar para a lista