Resumo
Implemente limitação de taxa de API usando algoritmos de token bucket ou janela deslizante. Retorne cabeçalhos padrão IETF de limite de taxa (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset) e 429 Too Many Requests quando os limites forem excedidos. A PetstoreAPI Moderna implementa limitação de taxa com cotas por usuário e respostas de erro claras.
Introdução
Um cliente faz 10.000 requisições à sua API em um minuto. Seu banco de dados trava. Seus alertas de monitoramento disparam. Seus outros clientes não conseguem acessar a API. Você está sob ataque — ou talvez apenas lidando com um cliente com erro em um loop de repetição.
A limitação de taxa evita isso. Ela define um limite para quantas requisições um cliente pode fazer em uma janela de tempo. Quando o limite é excedido, você retorna 429 Too Many Requests. O cliente recua, e sua API permanece saudável.
A antiga Swagger Petstore não implementa limitação de taxa. A PetstoreAPI Moderna implementa limitação de taxa com cabeçalhos IETF padrão, cotas por usuário e respostas de erro claras.
Neste guia, você aprenderá algoritmos de limitação de taxa, cabeçalhos padrão e como a PetstoreAPI Moderna implementa a limitação de taxa corretamente.
Por Que APIs Precisam de Limitação de Taxa
A limitação de taxa protege sua API contra abusos e garante o uso justo.
Proteção Contra Abuso
1. Ataques de Negação de Serviço (DoS)
Um invasor inunda sua API com requisições para torná-la indisponível. A limitação de taxa limita o impacto.
2. Credential stuffing (preenchimento de credenciais)
Invasores tentam milhares de combinações de nome de usuário/senha. A limitação de taxa os desacelera.
3. Raspagem de dados
Bots raspam todo o seu conjunto de dados. A limitação de taxa torna a raspagem impraticável.
4. Controle de custos
Se sua API chama serviços caros (modelos de IA, APIs de terceiros), a limitação de taxa impede custos excessivos.
Uso Justo
1. Evitar que um cliente monopolize recursos
Sem limitação de taxa, um cliente fazendo 1000 requisições/segundo pode prejudicar outros clientes.
2. Desempenho previsível
A limitação de taxa garante tempos de resposta consistentes para todos os clientes.
3. Acesso por níveis (tiers)
Nível gratuito: 100 requisições/hora. Nível pago: 10.000 requisições/hora. A limitação de taxa impõe esses níveis.
Benefícios Operacionais
1. Planejamento de capacidade
Você sabe a carga máxima que sua API suportará.
2. Previsibilidade de custos
Limites de taxa limitam os custos de infraestrutura.
3. Degradação elegante
Sob carga, a limitação de taxa evita falhas em cascata.
Algoritmos de Limitação de Taxa
Diferentes algoritmos possuem diferentes trade-offs (compromissos).
1. Janela Fixa
Conta requisições em janelas de tempo fixas.
Como funciona:
Janela 1 (00:00-00:59): 100 requisições permitidas
Janela 2 (01:00-01:59): 100 requisições permitidas
Implementação:
def is_allowed(user_id):
current_minute = get_current_minute()
key = f"rate_limit:{user_id}:{current_minute}"
count = redis.incr(key)
redis.expire(key, 60)
return count <= 100
Prós:
- Simples de implementar
- Baixo uso de memória
Contras:
- Problema de rajada: O cliente pode fazer 100 requisições às 00:59 e 100 às 01:00 (200 em 2 segundos)
2. Janela Deslizante
Conta requisições em uma janela de tempo contínua.
Como funciona:
Às 01:30, conta requisições das 00:30 às 01:30 (últimos 60 minutos).
Implementação:
def is_allowed(user_id):
now = time.time()
window_start = now - 3600 # 1 hour ago
key = f"rate_limit:{user_id}"
# Remove old requests
redis.zremrangebyscore(key, 0, window_start)
# Count requests in window
count = redis.zcard(key)
if count < 100:
redis.zadd(key, {now: now})
redis.expire(key, 3600)
return True
return False
Prós:
- Sem problema de rajada
- Limitação de taxa precisa
Contras:
- Maior uso de memória (armazena timestamp para cada requisição)
- Mais complexo
3. Token Bucket (Balde de Tokens)
Tokens são adicionados a um balde a uma taxa fixa. Cada requisição consome um token.
Como funciona:
Capacidade do balde: 100 tokens
Taxa de reabastecimento: 10 tokens/segundo
Requisição: consome 1 token
Implementação:
def is_allowed(user_id):
now = time.time()
key = f"rate_limit:{user_id}"
# Get current state
data = redis.hgetall(key)
tokens = float(data.get('tokens', 100))
last_refill = float(data.get('last_refill', now))
# Refill tokens
elapsed = now - last_refill
tokens = min(100, tokens + elapsed * 10) # 10 tokens/sec
if tokens >= 1:
tokens -= 1
redis.hset(key, 'tokens', tokens)
redis.hset(key, 'last_refill', now)
redis.expire(key, 3600)
return True
return False
Prós:
- Permite rajadas (até a capacidade do balde)
- Limitação de taxa suave
- Padrão da indústria
Contras:
- Mais complexo que janela fixa
- Requer armazenamento de estado
4. Leaky Bucket (Balde Furado)
Requisições são adicionadas a uma fila e processadas a uma taxa fixa.
Como funciona:
Capacidade da fila: 100 requisições
Taxa de processamento: 10 requisições/segundo
Prós:
- Taxa de saída suave
- Bom para proteger serviços a jusante
Contras:
- Adiciona latência (requisições esperam na fila)
- Complexo de implementar
Qual Algoritmo Usar?
Para a maioria das APIs: Token Bucket
É o padrão da indústria, permite rajadas razoáveis e oferece limitação de taxa suave.
A PetstoreAPI Moderna usa token bucket com cotas por usuário.
Cabeçalhos Padrão de Limite de Taxa
Use cabeçalhos padrão IETF (draft-ietf-httpapi-ratelimit-headers).
Cabeçalhos Padrão
RateLimit-Limit: Máximo de requisições permitidas na janela de tempo
RateLimit-Limit: 100
RateLimit-Remaining: Requisições restantes na janela atual
RateLimit-Remaining: 45
RateLimit-Reset: Segundos até o limite de taxa ser redefinido
RateLimit-Reset: 3600
Exemplo de Resposta
GET /pets
200 OK
RateLimit-Limit: 100
RateLimit-Remaining: 99
RateLimit-Reset: 3600
{
"data": [...]
}
Cabeçalhos Legados (Descontinuados)
Muitas APIs usam cabeçalhos não padrão:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1710331200
Não use estes. O prefixo X- é descontinuado, e o formato não é padronizado.
Como a PetstoreAPI Moderna Implementa a Limitação de Taxa
A PetstoreAPI Moderna implementa a limitação de taxa de token bucket com cabeçalhos padrão.
Limites de Taxa por Nível
Nível gratuito:
- 100 requisições/hora
- 1.000 requisições/dia
Nível Pro:
- 10.000 requisições/hora
- 100.000 requisições/dia
Nível Enterprise:
- Limites personalizados
Implementação
Requisição bem-sucedida:
GET /v1/pets
200 OK
RateLimit-Limit: 100
RateLimit-Remaining: 99
RateLimit-Reset: 3540
{
"data": [...]
}
Limite de taxa excedido:
GET /v1/pets
429 Too Many Requests
Content-Type: application/problem+json
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 120
Retry-After: 120
{
"type": "https://petstoreapi.com/errors/rate-limit-exceeded",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "Você excedeu o limite de taxa de 100 requisições por hora",
"instance": "/v1/pets",
"retryAfter": 120,
"limit": 100,
"window": "1h"
}
Por Usuário vs Por IP
Por usuário (requisições autenticadas):
Limite de taxa por ID de usuário ou chave de API. Mais preciso e justo.
user_id = get_authenticated_user()
is_allowed(user_id)
Por IP (requisições não autenticadas):
Limite de taxa por endereço IP. Menos preciso (IPs compartilhados, VPNs), mas melhor do que nada.
ip_address = request.remote_addr
is_allowed(ip_address)
A PetstoreAPI Moderna usa limitação de taxa por usuário para requisições autenticadas e por IP para endpoints públicos.
Formato da Resposta de Limite de Taxa
Quando os limites de taxa são excedidos, retorne 429 com formato de erro RFC 9457.
Estrutura da Resposta
{
"type": "https://petstoreapi.com/errors/rate-limit-exceeded",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "Você excedeu seu limite de taxa. Por favor, tente novamente mais tarde.",
"instance": "/v1/pets",
"retryAfter": 120,
"limit": 100,
"remaining": 0,
"reset": 120,
"window": "1h"
}
Cabeçalhos
429 Too Many Requests
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 120
Retry-After: 120
Retry-After: Informa aos clientes quando tentar novamente (em segundos).
Testando Limites de Taxa com Apidog
O Apidog ajuda você a testar o comportamento de limitação de taxa.
Cenários de Teste
1. Uso normal:
Enviar 50 requisições → Todas bem-sucedidas
Verificar se RateLimit-Remaining diminui
2. Exceder limite:
Enviar 101 requisições → A 101ª retorna 429
Verificar formato da resposta de erro
Verificar cabeçalho Retry-After
3. Comportamento de reset:
Exceder limite → Esperar o reset → Verificar se o limite foi restaurado
4. Diferentes níveis:
Testar nível gratuito (100/hora)
Testar nível pro (10.000/hora)
Verificar se os limites são aplicados corretamente
Exemplo de Teste com Apidog
// Testar cabeçalhos de limite de taxa
pm.test("Rate limit headers present", () => {
pm.response.to.have.header("RateLimit-Limit");
pm.response.to.have.header("RateLimit-Remaining");
pm.response.to.have.header("RateLimit-Reset");
});
// Testar limite de taxa excedido
pm.test("Returns 429 when limit exceeded", () => {
// Fazer 101 requisições
for (let i = 0; i < 101; i++) {
pm.sendRequest("GET /v1/pets");
}
pm.response.to.have.status(429);
});
Melhores Práticas de Limitação de Taxa
1. Use cabeçalhos padrão
Use cabeçalhos padrão IETF, não cabeçalhos X- personalizados.
2. Retorne 429, não 403
429 significa “requisições demais”. 403 significa “proibido”. Não os confunda.
3. Inclua Retry-After
Informe aos clientes quando eles podem tentar novamente.
4. Documente seus limites
Torne os limites de taxa visíveis na documentação.
5. Ofereça diferentes níveis
Nível gratuito: limites baixos. Nível pago: limites mais altos.
6. Limite de taxa por usuário, não por IP
Limites por usuário são mais precisos e justos.
7. Permita rajadas
O token bucket permite rajadas razoáveis sem penalizar o uso normal.
8. Monitore os acionamentos de limite de taxa
Acompanhe a frequência com que os clientes atingem os limites de taxa. Taxas altas indicam problemas.
9. Forneça um endpoint de status de limite de taxa
GET /v1/rate-limit
200 OK
{
"limit": 100,
"remaining": 45,
"reset": 3540
}
10. Teste a limitação de taxa
Use o Apidog para testar o comportamento de limite de taxa antes da implantação.
Conclusão
A limitação de taxa protege sua API contra abusos e garante o uso justo. Use o algoritmo token bucket com cabeçalhos IETF padrão (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset). Retorne 429 Too Many Requests com formato de erro RFC 9457 quando os limites forem excedidos.
A PetstoreAPI Moderna implementa a limitação de taxa corretamente com cotas por usuário, cabeçalhos padrão e respostas de erro claras. Verifique a documentação para detalhes de implementação.
Teste sua limitação de taxa com o Apidog para garantir que ela funcione corretamente sob carga e lide com casos extremos de forma adequada.
Perguntas Frequentes
Quais limites de taxa devo definir?
Comece conservador: 100 requisições/hora para o nível gratuito, 10.000/hora para o pago. Ajuste com base nos padrões de uso e capacidade da infraestrutura.
Devo limitar a taxa por IP ou por usuário?
Limite a taxa por usuário (chave de API) para requisições autenticadas. Use a limitação de taxa baseada em IP apenas para endpoints públicos.
O que acontece se um cliente excede o limite de taxa?
Retorne 429 Too Many Requests com o cabeçalho Retry-After. Não bloqueie o cliente permanentemente — deixe-o tentar novamente após a janela ser redefinida.
Como lido com limites de taxa para webhooks?
Webhooks são de servidor para servidor, então os limites de taxa devem ser mais altos. Considere limites separados para webhooks vs chamadas de API.
Devo limitar a taxa de serviços internos?
Sim, mas com limites muito mais altos. A limitação de taxa evita falhas em cascata mesmo em sistemas internos.
Como testo a limitação de taxa?
Use o Apidog para enviar múltiplas requisições e verificar respostas 429, cabeçalhos de limite de taxa e comportamento de reset.
E se minha API estiver atrás de um CDN?
O cache do CDN reduz a carga, mas você ainda precisa de limitação de taxa para cache misses e requisições POST/PUT/DELETE.
Como implemento a limitação de taxa em múltiplos servidores?
Use um armazenamento de dados compartilhado (Redis, Memcached) para rastrear os limites de taxa em todos os servidores. Não use memória local — não funcionará em sistemas distribuídos.
