Projetando um Rate Limiter Global: Guia Completo de System Design

Resumo: Um guia de arquitetura em nível de produção para construir rate limiting distribuído em APIs e microsserviços, cobrindo algoritmos, armazenamento de estado, trade-offs de consistência global, quotas por tenant, limites adaptativos, resistência a abuso e operação observável.

Publicado: Fevereiro 2026

Tempo de leitura: 80 minutos

Palavras-chave: #SystemDesign #RateLimiter #APIGateway #Quota #SistemasDistribuídos #Escalabilidade #Confiabilidade #EntrevistaTécnica

Às 09:00, seu tráfego está normal. Às 09:01, uma versão bugada do cliente dispara retries sem backoff. Às 09:02, um tenant enterprise inicia backfill massivo. Às 09:03, bots iniciam credential stuffing.

Sem rate limiting, tudo compartilha o mesmo colapso.

Com rate limiting fraco, usuários legítimos são bloqueados enquanto abuso continua passando.

Rate limiter sério não é só contador:

  • protege disponibilidade,
  • garante fairness,
  • aplica plano comercial,
  • limita custo operacional,
  • reduz blast radius.

Este guia detalha um desenho de nível senior para entrevistas e produção.

Sumário

  • Análise de Requisitos
  • Cálculos de Envelope
  • Arquitetura de Alto Nível
  • Escolha de Algoritmos
  • Contrato de API de Decisão
  • Modelagem de Dados e Chaves
  • Limiting Embutido no Gateway (Core 1)
  • Serviço Distribuído de Decisão (Core 2)
  • Quotas Globais e Regionais (Core 3)
  • Burst e Suavização (Core 4)
  • Políticas por Plano e Tenant (Core 5)
  • Limites Adaptativos por Risco (Core 6)
  • Idempotência e Retries (Core 7)
  • Resistência a Abuso e Evasão (Core 8)
  • Caching e Estratégia de Storage
  • Confiabilidade e Degradação
  • Observabilidade e SLOs
  • Dicas de Entrevista
  • Anti-Patterns
  • Conclusão
  • Referências
  • Referência Rápida

Análise de Requisitos

Requisitos Funcionais

  1. Aplicar limite por chave e janela configurável.
  2. Suportar dimensões: user, API key, tenant, IP, rota, método.
  3. Retornar decisão ALLOW/DENY com motivo.
  4. Expor remaining, reset e retry_after.
  5. Suportar burst + limite sustentado.
  6. Suportar quotas hierárquicas.
  7. Atualizar políticas sem restart global.
  8. Gerar logs de decisão para analytics e forense.

Requisitos Não Funcionais

Requisito

Meta

Motivo

Latência de decisão

< 5ms p99 no gateway

limiter não pode virar gargalo

Disponibilidade

99,99%

camada de proteção crítica

Throughput

milhões de checks/s

praticamente todo request passa por aqui

Correção

erro bounded em distribuição

fairness e confiança de billing

Propagação de policy

< 30s

resposta operacional rápida

Isolamento

tenants ruidosos contidos

proteger plataforma compartilhada

Perguntas de Clarificação

  1. Consistência global estrita é obrigatória?
  2. Quota impacta billing hard?
  3. Edge-only ou também service-to-service?
  4. Qual taxa tolerável de falso bloqueio?
  5. Em falha, fail-open ou fail-closed?

Premissas:

  • enforcement no API gateway,
  • SaaS multi-tenant,
  • deploy multi-região,
  • limites hard para billing,
  • limites soft para cenários de risco baixo.

Cálculos de Envelope

Escala Assumida

Requests/dia: 90 bilhõesRPS médio: ~1.041.667RPS pico: 6.000.000Chaves ativas/dia: 80 milhõesPolicies ativas: 300 mil

Throughput de Decisão

Checks/s médio ~= 1,04MChecks/s pico ~= 6M

Check envolve:

  • parse de dimensões,
  • lookup de policy,
  • operação atômica de contador,
  • retorno de cabeçalhos.

Estado Quente

Se cada estado de contador ativo for ~120 bytes:

80M * 120B ~= 9,6GB estado quente mínimo

Na prática, multiplica por réplicas, dimensões e janelas.

Logging

Se logar 10% das decisões (180B cada):

90B * 0,1 * 180B ~= 1,62TB/dia

Insight

O desafio central é latência baixa + consistência suficiente + comportamento previsível em falhas.

Arquitetura de Alto Nível

flowchart TB subgraph Clientes APP["Apps/SDKs"] INT["Integrações Externas"] end subgraph Edge CDN["CDN"] WAF["WAF/Bot Filter"] GATE["API Gateway"] LOCAL["Local Limiter Cache"] end subgraph Control Plane POLICY["Policy Service"] ADMIN["Admin API"] DIST["Policy Distribution"] end subgraph Data Plane DECIDE["Decision Service"] COUNTER["Counter Store"] RISK["Risk Service"] end subgraph Analytics BUS[("Kafka")] OLAP[("Warehouse")] ALERT["Alerting"] end APP --> CDN --> WAF --> GATE INT --> CDN GATE --> LOCAL GATE --> DECIDE POLICY --> DIST DIST --> GATE DIST --> DECIDE DECIDE --> COUNTER DECIDE --> RISK GATE --> BUS DECIDE --> BUS BUS --> OLAP BUS --> ALERT ADMIN --> POLICY

Princípios

  1. Fast-path local no gateway.
  2. Counter store distribuído para rigor.
  3. Control plane separado do data plane.
  4. Fail mode por criticidade de endpoint.

Escolha de Algoritmos

Fixed Window

  • simples e barato,
  • problema de burst na borda da janela.

Sliding Log

  • precisão alta,
  • custo alto de memória/CPU.

Sliding Window Counter

  • equilíbrio bom,
  • comum em produção.

Token Bucket

  • excelente para burst controlado,
  • muito usado em API gateways.

Leaky Bucket

  • suaviza saída,
  • bom para proteger downstream.

Recomendação Prática

  • token bucket para shaping por cliente,
  • sliding window para quotas de plano,
  • composição hierárquica de algoritmos.

Algoritmo

Precisão

Custo

Burst

Fixed

média-baixa

baixo

fraco

Sliding Log

alta

alto

médio

Sliding Counter

alta

médio

médio

Token Bucket

alta

baixo-médio

forte

Leaky Bucket

média

médio

controlado

Contrato de API de Decisão

POST /internal/v1/limit/check

Request:

{ "request_id": "req_901", "subject": { "tenant_id": "t_44", "api_key_id": "k_77", "user_id": "u_12", "ip": "203.0.113.8" }, "resource": { "route": "/v1/payments", "method": "POST", "service": "payments-api" }, "context": { "region": "us-east-1", "risk_score": 0.14 }}

Response allow:

{ "decision": "ALLOW", "applied_policy_id": "policy_payments_post_tier2", "remaining": 127, "reset_after_ms": 1820, "retry_after_ms": 0, "reason": "WITHIN_LIMIT", "limit_headers": { "x-ratelimit-limit": "200", "x-ratelimit-remaining": "127", "x-ratelimit-reset": "2" }}

Response deny:

{ "decision": "DENY", "applied_policy_id": "policy_payments_post_tier2", "remaining": 0, "reset_after_ms": 780, "retry_after_ms": 780, "reason": "TOKEN_BUCKET_EMPTY"}

Modelagem de Dados e Chaves

Padrão de Chave de Contador

rl:{policy_id}:{tenant_id}:{api_key_id}:{route_hash}:{window_bucket}

Exemplo de Policy

{ "policy_id": "policy_payments_post_tier2", "scope": { "tenant_tier": "PRO", "route": "/v1/payments", "method": "POST" }, "algorithm": "TOKEN_BUCKET", "config": { "capacity": 200, "refill_per_sec": 50 }, "mode": "HARD", "fail_behavior": "FAIL_CLOSED", "priority": 900, "enabled": true, "updated_at": "2026-02-22T22:10:00Z"}

Quotas Hierárquicas

{ "quota_tree": [ { "level": "TENANT", "limit": "50000/min" }, { "level": "API_KEY", "limit": "1000/min" }, { "level": "ROUTE", "limit": "200/min" } ]}

Boas Práticas

  1. TTL para buckets.
  2. Policy versionada.
  3. Separar hot counters de histórico analítico.

Limiting Embutido no Gateway (Core 1)

Vantagens

  1. menos hop de rede,
  2. bloqueio antecipado,
  3. melhor custo por decisão.

Fluxo Híbrido

sequenceDiagram participant C as Cliente participant G as Gateway participant L as Local Limiter participant R as Remote Limiter C->>G: request G->>L: local check alt local deny L-->>G: deny G-->>C: 429 else local allow L-->>G: provisional allow G->>R: strict/global check (if needed) alt remote deny R-->>G: deny G-->>C: 429 else allow R-->>G: allow G-->>C: forward upstream end end

Trade-off

Só local = rápido, menos preciso globalmente.

Híbrido = bom equilíbrio.

Serviço Distribuído de Decisão (Core 2)

Responsabilidades

  1. resolver policy,
  2. atualizar contador atômico,
  3. retornar decisão,
  4. emitir evento de auditoria.

Atomicidade

Use script atômico (ex: Lua em Redis) para check + decrement.

Sem atomicidade, concorrência cria allow indevido.

Particionamento

Shard por hash(policy + subject).

Multi-DC

Global estrito em todo request costuma estourar latência. Para muitos cenários, bounded inconsistency com controle é melhor.

Quotas Globais e Regionais (Core 3)

Problema

Tenant global com limite diário, tráfego distribuído em várias regiões.

Opção Prática: Budget Leasing

  • gerenciador global entrega "lotes de quota" para regiões,
  • região consume localmente com baixa latência,
  • solicita novo lote quando perto do fim.

flowchart LR GQ["Global Quota Manager"] --> R1["Region A Lease"] GQ --> R2["Region B Lease"] GQ --> R3["Region C Lease"] R1 --> C1["Local Counter"] R2 --> C2["Local Counter"] R3 --> C3["Local Counter"]

Trade-offs

  • pequena discrepância temporal,
  • grande ganho de latência/disponibilidade.

Burst e Suavização (Core 4)

Regra Composta

Combinar:

  1. limite de burst curto,
  2. limite sustentado longo.

ALLOW se burst_ok && sustained_ok

Retry-After com Jitter

Retornar retry com jitter ajuda a evitar retry storm sincronizado.

Políticas por Plano e Tenant (Core 5)

Exemplo de Plano

Plano

Limite Global

Burst

Free

60/min

10/5s

Pro

3.000/min

200/5s

Enterprise

custom

custom

Ordem de Resolução

  1. bloqueio emergencial,
  2. override de tenant,
  3. default de plano,
  4. ajuste por rota,
  5. fallback anônimo.

Requisito

Mudança de policy sem redeploy em massa.

Limites Adaptativos por Risco (Core 6)

Inputs

  1. risco comportamental,
  2. taxa de falha de auth,
  3. detecção de anomalia,
  4. sensibilidade da rota,
  5. status de incidente regional.

Exemplo

if risk_score > 0.9 -> reduzir limite 80%if 0.7 <= risk_score <= 0.9 -> reduzir 40%else -> limite padrão

Guardrails

  • limite máximo de ajuste,
  • decaimento temporal,
  • whitelist controlada para integrações críticas.

Idempotência e Retries (Core 7)

Questão

Retry de request idempotente deve consumir quota novamente?

Modelos

  1. cobrar tentativa (mais simples, mais duro),
  2. cobrar chave idempotente única (mais justo em rede instável).

Recomendação

  • endpoints financeiros: considerar dedupe por idempotency-key,
  • endpoints de risco/abuso: cobrar tentativa.

Chave de Dedupe

(api_key, idempotency_key, route)

Resistência a Abuso e Evasão (Core 8)

Táticas de Evasão

  1. rotação de IP,
  2. troca de API keys,
  3. low-and-slow distribuído,
  4. user-agent aleatório.

Defesa em Camadas

  1. chave multidimensional,
  2. WAF antes do limiter,
  3. score de comportamento,
  4. challenge progressivo,
  5. sinais de honeypot.

Regra Prática

DENY se qualquer dimensão hard estourarTHROTTLE para risco moderadoALLOW com observabilidade para tráfego normal

Caching e Estratégia de Storage

Split de Dados

  1. counters quentes em in-memory,
  2. policies em config store durável,
  3. logs em stream + warehouse.

Caches

  • local policy cache,
  • negative cache curto para blocos recentes,
  • cache de decisão repetida em janelas curtíssimas.

TTLs

  • bucket TTL alinhado com janela,
  • deny cache curto,
  • policy cache com invalidação por versão.

Confiabilidade e Degradação

Falhas

  1. counter store fora,
  2. policy stale,
  3. partição inter-região,
  4. skew de clock.

Matrix de Fail Mode

Tipo de endpoint

Comportamento

pagamento/crítico

fail-closed ou fallback estrito

leitura geral

fail-open com caps emergenciais

interno baixo risco

fail-open com telemetria

Plano de Degradação

  1. ativar limites estáticos locais,
  2. apertar dimensões de alto risco,
  3. desligar lógica adaptativa custosa,
  4. preservar disponibilidade core.

Observabilidade e SLOs

SLOs

SLI

SLO

latência de decisão p99

< 5ms

disponibilidade

> 99,99%

lag de propagação de policy p95

< 30s

falso bloqueio em coorte válida

abaixo da meta

erro do counter store

dentro do error budget

Golden Signals

  1. allow/deny por rota/tenant,
  2. latência de decisão,
  3. tempo de comando no counter store,
  4. skew de versão de policy,
  5. fail-open activation.

Trace

x-request-idx-tenant-idx-api-key-idx-policy-idx-rate-limit-decision

Dicas de Entrevista

Estrutura

  1. Clarifique dimensões e rigidez.
  2. Justifique algoritmo.
  3. Desenhe gateway + serviço distribuído.
  4. Explique quotas globais por lease.
  5. Trate fail mode por criticidade.
  6. Feche com observabilidade e abuse.

Erros Comuns

  1. contador global único para tudo,
  2. policy hardcoded,
  3. sem idempotência,
  4. sem plano de degradação,
  5. sem estratégia anti-evasão.

Script Curto

  1. fast check local,
  2. strict check remoto quando necessário,
  3. limites hierárquicos,
  4. lease regional para quota global,
  5. fail-open/closed por endpoint.

Anti-Patterns

1) Limitar só por IP

Problema: evasão fácil e falso bloqueio por NAT.

Correção: chaves multidimensionais.

2) Limites hardcoded no código

Problema: resposta lenta a incidentes.

Correção: policy service versionado.

3) Check/decrement não atômico

Problema: race condition em alta concorrência.

Correção: operação atômica.

4) Consistência global estrita para tudo

Problema: latência/availability ruins.

Correção: consistência pragmática por risco.

5) Fail-open sempre

Problema: abuso passa livre em falha.

Correção: matrix de fail behavior.

6) Sem headers de limite

Problema: cliente não sabe quando retryar.

Correção: Retry-After e headers padrão.

7) Sem monitorar skew de policy

Problema: comportamento inconsistente por região.

Correção: monitoramento e alerta de convergência.

Conclusão

Rate limiter de produção é uma camada distribuída de controle de risco e capacidade.

Arquitetura madura combina:

  1. decisão rápida na borda,
  2. estado distribuído com atomicidade,
  3. políticas flexíveis por plano,
  4. adaptação por risco,
  5. degradação previsível,
  6. observabilidade forte.

Esse é um dos temas mais recorrentes em entrevistas porque separa respostas superficiais de engenharia realmente pragmática.

Referências

Referência Rápida

Componentes

Componente

Responsabilidade

API Gateway

enforcement inicial

Local Limiter Cache

check ultrarrápido

Decision Service

decisão estrita distribuída

Counter Store

estado atômico de bucket

Policy Service

definição e distribuição

Risk Service

ajuste adaptativo

Analytics Pipeline

visibilidade e tuning

Regras Críticas

  1. Separar control plane de data plane.
  2. Aplicar limites hierárquicos.
  3. Garantir atomicidade no contador.
  4. Definir fail mode por endpoint.
  5. Medir falso bloqueio e drift de policy.

Resumo de 10 minutos

1) Dimensões + criticidade.2) Token bucket + sliding window.3) Fast local + strict remoto.4) Quota global por lease regional.5) Observabilidade + abuse controls + degradação.

Você agora tem um blueprint completo para rate limiting distribuído em escala global.

Source

1 share