O padrão circuit breaker protege sua aplicação quando a API de CPF apresenta falhas persistentes: ao detectar um número excessivo de erros consecutivos, ele "abre o circuito" e interrompe temporariamente as chamadas, permitindo que o serviço se recupere sem sobrecarregar a infraestrutura.
Introdução
Quando uma API externa apresenta falhas persistentes, continuar enviando requisições não apenas não resolve o problema como pode agravar a situação — tanto para a API quanto para a sua aplicação. O padrão circuit breaker resolve esse problema ao "abrir o circuito" quando um número excessivo de falhas é detectado, interrompendo temporariamente as chamadas e permitindo que o serviço se recupere.
Como funciona o circuit breaker
O circuit breaker opera em três estados:
1. Fechado (Closed)
Estado normal de operação. Todas as requisições passam normalmente para a API. O circuit breaker monitora a taxa de falhas. Quando o número de falhas consecutivas atinge um limiar predefinido, o circuito "abre".
2. Aberto (Open)
Nenhuma requisição é enviada para a API. Todas as chamadas retornam imediatamente com um erro ou um valor de fallback. Após um período de espera (tempo de reset), o circuito passa para o estado "meio-aberto".
3. Meio-aberto (Half-Open)
Uma única requisição de teste é enviada para a API. Se essa requisição for bem-sucedida, o circuito volta ao estado "fechado". Se falhar, o circuito retorna ao estado "aberto" e o timer de reset é reiniciado.
Implementação em Python
import requests
import time
from enum import Enum
class Estado(Enum):
FECHADO = "fechado"
ABERTO = "aberto"
MEIO_ABERTO = "meio_aberto"
class CircuitBreaker:
def __init__(self, limiar_falhas=5, tempo_reset=30):
self.limiar_falhas = limiar_falhas
self.tempo_reset = tempo_reset
self.estado = Estado.FECHADO
self.falhas_consecutivas = 0
self.ultimo_tempo_falha = None
def pode_executar(self):
if self.estado == Estado.FECHADO:
return True
if self.estado == Estado.ABERTO:
tempo_passado = time.time() - self.ultimo_tempo_falha
if tempo_passado >= self.tempo_reset:
self.estado = Estado.MEIO_ABERTO
return True
return False
if self.estado == Estado.MEIO_ABERTO:
return True
return False
def registrar_sucesso(self):
self.falhas_consecutivas = 0
self.estado = Estado.FECHADO
def registrar_falha(self):
self.falhas_consecutivas += 1
self.ultimo_tempo_falha = time.time()
if self.falhas_consecutivas >= self.limiar_falhas:
self.estado = Estado.ABERTO
print(f"Circuit breaker ABERTO após {self.falhas_consecutivas} falhas")
def get_estado(self):
return self.estado.value
# Instância global do circuit breaker
cb = CircuitBreaker(limiar_falhas=5, tempo_reset=30)
def consultar_cpf(cpf):
if not cb.pode_executar():
return {
"erro": "Serviço temporariamente indisponível (circuit breaker aberto)",
"circuit_breaker": cb.get_estado()
}
url = f"https://api.cpfhub.io/cpf/{cpf}"
headers = {
"x-api-key": "SUA_CHAVE_DE_API",
"Accept": "application/json"
}
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
cb.registrar_sucesso()
return response.json()
if response.status_code in (500, 502, 503):
cb.registrar_falha()
return {"erro": f"Erro do servidor: {response.status_code}"}
# Erros do cliente (4xx) não devem acionar o circuit breaker
return {"erro": f"Erro: {response.status_code}"}
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError):
cb.registrar_falha()
return {"erro": "Timeout ou erro de conexão"}
# Uso
resultado = consultar_cpf("12345678900")
print(f"Estado do circuit breaker: {cb.get_estado()}")
print(resultado)
Implementação em JavaScript (Node.js)
class CircuitBreaker {
constructor(options = {}) {
this.limiarFalhas = options.limiarFalhas || 5;
this.tempoReset = options.tempoReset || 30000; // 30 segundos
this.estado = 'fechado';
this.falhasConsecutivas = 0;
this.ultimaFalha = null;
}
podeExecutar() {
if (this.estado === 'fechado') return true;
if (this.estado === 'aberto') {
const tempoPassado = Date.now() - this.ultimaFalha;
if (tempoPassado >= this.tempoReset) {
this.estado = 'meio_aberto';
return true;
}
return false;
}
return this.estado === 'meio_aberto';
}
registrarSucesso() {
this.falhasConsecutivas = 0;
this.estado = 'fechado';
}
registrarFalha() {
this.falhasConsecutivas++;
this.ultimaFalha = Date.now();
if (this.falhasConsecutivas >= this.limiarFalhas) {
this.estado = 'aberto';
console.log(
`Circuit breaker ABERTO após ${this.falhasConsecutivas} falhas`
);
}
}
}
const cb = new CircuitBreaker({ limiarFalhas: 5, tempoReset: 30000 });
async function consultarCPF(cpf) {
if (!cb.podeExecutar()) {
return {
erro: 'Serviço temporariamente indisponível',
circuitBreaker: cb.estado
};
}
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000);
try {
const response = await fetch(
`https://api.cpfhub.io/cpf/${cpf}`,
{
headers: {
'x-api-key': 'SUA_CHAVE_DE_API',
'Accept': 'application/json'
},
signal: controller.signal
}
);
clearTimeout(timeoutId);
if (response.ok) {
cb.registrarSucesso();
return await response.json();
}
if ([500, 502, 503].includes(response.status)) {
cb.registrarFalha();
return { erro: `Erro do servidor: ${response.status}` };
}
return { erro: `Erro: ${response.status}` };
} catch (error) {
clearTimeout(timeoutId);
cb.registrarFalha();
return { erro: error.name === 'AbortError' ? 'Timeout' : error.message };
}
}
Quando o circuit breaker deve abrir
O circuit breaker deve ser acionado apenas por falhas que indicam um problema no servidor ou na rede — nunca por erros do cliente:
-
Acionar o circuit breaker — Erros 5xx (500, 502, 503), timeouts e erros de conexão.
-
Não acionar o circuit breaker — Erros 4xx como 400 (CPF inválido), 401 (API key incorreta) e 404 (CPF não encontrado). Esses erros são previsíveis e não indicam instabilidade da API. Vale lembrar que a API CPFHub.io não retorna HTTP 429: ao superar o limite do plano gratuito, ela cobra R$0,15 por consulta adicional sem bloquear as requisições.
Combinando circuit breaker com fallback
Quando o circuit breaker está aberto, em vez de simplesmente retornar um erro, a aplicação pode oferecer um fallback:
-
Cache — Retornar o último resultado conhecido para aquele CPF.
-
Fila — Enfileirar a consulta para processamento posterior.
-
Degradação graceful — Prosseguir com o fluxo sem a validação de CPF, sinalizando que a verificação será feita posteriormente.
import redis
import json
redis_client = redis.Redis(host='localhost', port=6379, db=0)
def consultar_cpf_com_fallback(cpf):
if not cb.pode_executar():
# Fallback: tentar cache
cached = redis_client.get(f"cpf_cache:{cpf}")
if cached:
dados = json.loads(cached)
dados["fonte"] = "cache"
return dados
return {
"erro": "Serviço indisponível e sem cache disponível",
"acao": "enfileirado_para_reprocessamento"
}
url = f"https://api.cpfhub.io/cpf/{cpf}"
headers = {
"x-api-key": "SUA_CHAVE_DE_API",
"Accept": "application/json"
}
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
cb.registrar_sucesso()
dados = response.json()
# Atualizar cache
if dados.get("success"):
redis_client.setex(
f"cpf_cache:{cpf}",
86400,
json.dumps(dados)
)
return dados
cb.registrar_falha()
return {"erro": f"HTTP {response.status_code}"}
except Exception:
cb.registrar_falha()
return {"erro": "Falha na requisição"}
Configurando os parâmetros ideais
| Parâmetro | Recomendação | Justificativa |
|---|---|---|
| Limiar de falhas | 3-5 falhas consecutivas | Baixo o suficiente para reagir rápido |
| Tempo de reset | 15-60 segundos | Tempo razoável para recuperação |
| Timeout da requisição | 10 segundos | Compatível com o tempo de resposta da API |
Para a API da CPFHub.io, recomenda-se timeout de 10 segundos — valor conservador que acomoda a latência típica de ~900ms e deixa margem para picos ocasionais sem disparar o circuit breaker prematuramente.
Monitorando o circuit breaker
Registre as transições de estado do circuit breaker em seus logs e métricas:
- Abertura do circuito — Indica que a API está enfrentando problemas.
- Fechamento do circuito — Indica que o problema foi resolvido.
- Tentativas em estado meio-aberto — Mostram a frequência das verificações de recuperação.
Essas métricas ajudam a identificar padrões de instabilidade e a ajustar os parâmetros ao longo do tempo. O OWASP API Security Top 10 recomenda monitoramento ativo de dependências externas como parte das boas práticas de segurança em integrações.
Perguntas frequentes
O circuit breaker é necessário mesmo quando a API tem alta disponibilidade?
Sim. Nenhuma API externa tem 100% de disponibilidade garantida, e falhas transitórias de rede podem ocorrer independentemente do SLA do provedor. O circuit breaker protege sua aplicação durante esses intervalos curtos — sem ele, requisições em cascata podem sobrecarregar tanto o servidor externo quanto o seu próprio backend em momentos de instabilidade.
Qual o limiar de falhas recomendado para integrações com API de CPF?
Para consultas de CPF em fluxos de cadastro, 3 a 5 falhas consecutivas é um limiar razoável. Com volume alto (onboarding em massa), prefira 5 falhas para evitar aberturas falsas por variações normais de latência. Com volume baixo, 3 falhas já é suficiente para detectar instabilidade real sem atrasar a resposta ao usuário.
O que acontece com as consultas enfileiradas quando o circuito fecha novamente?
Depende da estratégia de fallback implementada. Se a aplicação usou uma fila de reprocessamento, as consultas pendentes são processadas após o fechamento do circuito. Se usou degradação graceful (marcando registros para revisão posterior), um job pode buscar os registros pendentes e revalidar os CPFs assim que a conectividade for restabelecida.
O circuit breaker interfere no comportamento de cobrança por excedente da CPFHub.io?
Não. A lógica de cobrança fica inteiramente no servidor da API. O circuit breaker apenas decide se a sua aplicação envia ou não a requisição. Consultas bem-sucedidas são contabilizadas normalmente; consultas bloqueadas pelo circuit breaker não chegam ao servidor e, portanto, não são cobradas.
Conclusão
O circuit breaker é um padrão de resiliência essencial para qualquer integração com APIs externas. Ao interromper temporariamente as chamadas quando a API apresenta falhas persistentes, ele protege tanto a sua aplicação quanto o serviço externo, permitindo uma recuperação mais rápida e uma experiência de usuário mais estável.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e implemente o circuit breaker desde o primeiro dia para garantir que sua integração resista a qualquer instabilidade de rede.
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.



