Rate limiting no cliente e exponential backoff são padrões complementares que tornam seu sistema resiliente ao consumir APIs de CPF: o rate limiter controla o ritmo das requisições para preservar sua cota mensal, enquanto o backoff exponencial com jitter garante recuperação elegante em falhas de rede ou indisponibilidade temporária do servidor.
Introdução
Ao integrar a API de CPF do CPFHub.io, implementar rate limiting no lado do cliente e exponential backoff para retentativas são práticas essenciais que preservam sua cota de consultas, reduzem erros transitórios e tornam seu sistema mais resiliente. Essas técnicas são padrões de engenharia aplicáveis a qualquer API REST e ficam ainda mais relevantes quando o volume de consultas impacta diretamente o faturamento.
Entendendo rate limiting do lado do servidor
Antes de implementar o controle do lado do cliente, é importante entender como APIs comunicam seus limites através de headers de resposta.
| Header | Significado | Exemplo |
|---|---|---|
| X-RateLimit-Limit | Requisições permitidas por janela | 100 |
| X-RateLimit-Remaining | Requisições restantes na janela | 47 |
| X-RateLimit-Reset | Timestamp de reset da janela | 1704110400 |
| Retry-After | Segundos para esperar após erro | 30 |
# Python - Lendo headers de rate limit
import requests
import time
def consultar_com_awareness(cpf: str, api_key: str) -> dict:
response = requests.get(
f"https://api.cpfhub.io/cpf/{cpf}",
headers={"x-api-key": api_key}
)
remaining = int(response.headers.get("X-RateLimit-Remaining", 100))
reset_time = int(response.headers.get("X-RateLimit-Reset", 0))
if remaining < 10:
wait_time = max(0, reset_time - int(time.time()))
print(f"Atenção: apenas {remaining} requisições restantes. "
f"Reset em {wait_time}s")
response.raise_for_status()
return response.json()
- X-RateLimit-Remaining -- monitore este header para desacelerar proativamente antes de atingir o limite
- Retry-After -- em caso de erro de servidor, respeite este valor antes de tentar novamente
- Reset timestamp -- permite calcular exatamente quando a janela de rate limit reinicia
Implementando rate limiter no cliente (Python)
Controlar a taxa de requisições do lado do cliente preserva sua cota mensal e melhora a previsibilidade do processamento.
import time
import threading
from collections import deque
class RateLimiter:
def __init__(self, max_requests: int, window_seconds: float):
self.max_requests = max_requests
self.window = window_seconds
self.timestamps = deque()
self.lock = threading.Lock()
def acquire(self):
with self.lock:
now = time.monotonic()
# Remover timestamps fora da janela
while self.timestamps and self.timestamps[0] <= now - self.window:
self.timestamps.popleft()
if len(self.timestamps) >= self.max_requests:
wait_time = self.timestamps[0] + self.window - now
time.sleep(wait_time)
return self.acquire()
self.timestamps.append(now)
class CPFClientComLimite:
def __init__(self, api_key: str, max_rps: int = 10):
self.api_key = api_key
self.limiter = RateLimiter(max_requests=max_rps, window_seconds=1.0)
self.session = requests.Session()
self.session.headers["x-api-key"] = api_key
def consultar(self, cpf: str) -> dict:
self.limiter.acquire()
response = self.session.get(
f"https://api.cpfhub.io/cpf/{cpf}",
timeout=15
)
response.raise_for_status()
return response.json()
def consultar_lote(self, cpfs: list) -> list:
resultados = []
for i, cpf in enumerate(cpfs):
try:
resultado = self.consultar(cpf)
resultados.append({"cpf": cpf, "dados": resultado, "erro": None})
except Exception as e:
resultados.append({"cpf": cpf, "dados": None, "erro": str(e)})
if (i + 1) % 50 == 0:
print(f"Processados {i + 1}/{len(cpfs)} CPFs")
return resultados
| Configuração | Valor | Efeito |
|---|---|---|
| max_rps=10 | 10 req/s | Conservador, nunca atinge rate limit |
| max_rps=50 | 50 req/s | Moderado, monitora remaining |
| max_rps=100 | 100 req/s | Agressivo, precisa de backoff |
- Sliding window -- controle baseado em janela deslizante é mais preciso que contadores simples
- Thread-safe -- o lock garante que o rate limiter funcione corretamente em ambientes multi-thread
- Processamento em lote -- o rate limiter gerencia automaticamente o ritmo das requisições
Implementando rate limiter no cliente (JavaScript)
Em JavaScript, o rate limiter precisa funcionar com a event loop assíncrona.
class RateLimiter {
constructor(maxRequests, windowMs) {
this.maxRequests = maxRequests;
this.windowMs = windowMs;
this.timestamps = [];
this.queue = [];
}
async acquire() {
return new Promise((resolve) => {
this.queue.push(resolve);
this.#process();
});
}
#process() {
const now = Date.now();
this.timestamps = this.timestamps.filter(
(t) => t > now - this.windowMs
);
while (this.queue.length > 0 && this.timestamps.length < this.maxRequests) {
this.timestamps.push(now);
const resolve = this.queue.shift();
resolve();
}
if (this.queue.length > 0) {
const oldestTimestamp = this.timestamps[0];
const waitTime = oldestTimestamp + this.windowMs - now;
setTimeout(() => this.#process(), Math.max(waitTime, 10));
}
}
}
class CPFClientComLimite {
constructor(apiKey, maxRPS = 10) {
this.apiKey = apiKey;
this.limiter = new RateLimiter(maxRPS, 1000);
this.baseUrl = "https://api.cpfhub.io/cpf";
}
async consultar(cpf) {
await this.limiter.acquire();
const response = await fetch(`${this.baseUrl}/${cpf.replace(/\D/g, "")}`, {
headers: { "x-api-key": this.apiKey },
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
}
async consultarLote(cpfs) {
const resultados = [];
for (const cpf of cpfs) {
try {
const dados = await this.consultar(cpf);
resultados.push({ cpf, dados, erro: null });
} catch (error) {
resultados.push({ cpf, dados: null, erro: error.message });
}
}
return resultados;
}
}
- Promise queue -- requisições aguardam sua vez em uma fila quando o limite é atingido
- setTimeout -- agenda a próxima verificação para quando a janela reiniciar
- Processamento sequencial -- em lote, cada requisição respeita o rate limit automaticamente
Exponential backoff com jitter
Quando um retry é necessário por falha de rede ou erro de servidor, o backoff exponencial com jitter distribui as retentativas de forma inteligente, segundo as boas práticas de retry recomendadas pela AWS.
import random
import time
def exponential_backoff_retry(
func,
max_tentativas: int = 5,
base_delay: float = 1.0,
max_delay: float = 60.0,
jitter_strategy: str = "full"
):
for tentativa in range(max_tentativas):
try:
return func()
except Exception as e:
if tentativa == max_tentativas - 1:
raise
# Calcular delay com backoff exponencial
delay = min(base_delay * (2 ** tentativa), max_delay)
# Aplicar jitter
if jitter_strategy == "full":
delay = random.uniform(0, delay)
elif jitter_strategy == "equal":
delay = delay / 2 + random.uniform(0, delay / 2)
elif jitter_strategy == "decorrelated":
delay = random.uniform(base_delay, delay * 3)
print(f"Tentativa {tentativa + 1} falhou: {e}. "
f"Aguardando {delay:.1f}s")
time.sleep(delay)
# Uso com consulta de CPF
client = CPFClientComLimite(api_key="sua-chave", max_rps=10)
resultado = exponential_backoff_retry(
lambda: client.consultar("12345678909"),
max_tentativas=3,
base_delay=1.0
)
| Estratégia de jitter | Fórmula | Quando usar |
|---|---|---|
| Full jitter | random(0, delay) | Padrão recomendado pela AWS |
| Equal jitter | delay/2 + random(0, delay/2) | Quando precisa de delay mínimo |
| Decorrelated | random(base, delay*3) | Cenários de alta contenção |
| Sem jitter | delay fixo | Nunca em produção |
- Full jitter -- a estratégia mais recomendada, distribui retentativas uniformemente
- max_delay -- cap no delay máximo para evitar esperas absurdas após muitas falhas
- Decorrelated jitter -- cada retry é independente do anterior, reduzindo sincronização
Perguntas frequentes
A API da CPFHub.io retorna HTTP 429 quando o limite de consultas é atingido?
Não. A API da CPFHub.io nunca retorna HTTP 429 nem bloqueia requisições. Ao ultrapassar as 50 consultas mensais do plano gratuito (ou as 1.000 do plano Pro), cada consulta adicional é cobrada a R$ 0,15 automaticamente — o serviço continua disponível sem interrupção. O rate limiting descrito neste artigo é um padrão client-side para você controlar o ritmo das suas requisições e gerenciar sua cota, não uma resposta a bloqueios do servidor.
Por que implementar rate limiting no cliente se a API não bloqueia?
Porque o controle do lado do cliente serve a dois propósitos práticos: (1) distribuir o consumo ao longo do mês para evitar cobranças inesperadas de excedente, e (2) proteger sua infraestrutura de picos acidentais em processamentos em lote que poderiam gerar centenas de requisições em segundos. Trata-se de higiene de engenharia, não de uma obrigação imposta pelo servidor.
Quando o exponential backoff deve ser usado ao chamar a API de CPF?
O backoff exponencial é indicado para lidar com falhas de rede, timeouts e erros de servidor (5xx) — cenários transitórios onde a requisição pode ter sucesso em uma nova tentativa após breve espera. Para erros de CPF não encontrado (success: false) ou autenticação inválida (401), o retry não resolve: é necessário corrigir o dado ou a chave de API.
Qual é a latência esperada da API da CPFHub.io em produção?
A API da CPFHub.io responde em aproximadamente 900ms em condições normais. Ao configurar timeouts, use valores entre 10 e 15 segundos para absorver variações de rede sem tratar respostas legítimas como falhas. Com um rate limiter a 10 req/s, um lote de 1.000 CPFs processa em cerca de 100 segundos mais a latência de rede.
Conclusão
Rate limiting no cliente e exponential backoff são técnicas complementares que tornam seu sistema resiliente ao consumir APIs de CPF. O rate limiter preserva sua cota mensal e evita cobranças de excedente desnecessárias, enquanto o backoff exponencial com jitter garante recuperação elegante quando falhas de rede ou indisponibilidade temporária acontecem. Implemente ambas as técnicas desde o início do projeto e ajuste os parâmetros conforme os limites da sua conta.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e integre a API de CPF com os padrões de resiliência que seu sistema merece.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



