Guia prático para implementar retries exponenciais e circuit breaker em integrações entre ERP e marketplaces
Por Kevin Marcondes · Publicado em · 8 min de leitura
Este guia prático para implementar retries exponenciais e circuit breaker em integrações entre ERP e marketplaces mostra como manter resiliência sem duplicar pedidos ou violar limites de API. Você verá quando aplicar cada padrão, como configurar backoff com jitter, projetar idempotência e monitorar. Útil para equipes técnicas e responsáveis pelo negócio.
Quando usar retries e circuit breaker nas integrações ERP–marketplaces
Integrações com marketplaces sofrem com timeouts, picos de tráfego, janelas fiscais e rate limits. Retries exponenciais e circuit breaker estabilizam o fluxo, evitam quedas em cascata e reduzem retrabalho.
Sinais de que você precisa desses padrões: erros 429/5xx frequentes, duplicação de pedidos, estoque divergente, picos de latência e janelas de faturamento sensíveis ao tempo.
Em cenários de alto volume, combinar com filas ajuda a desacoplar e nivelar picos. Veja critérios em SQS vs RabbitMQ gerenciado.
- APIs com rate limit agressivo (429) no fechamento do mês.
- Time-outs intermitentes e DNS falhando esporadicamente.
- POSTs que, ao reprocessar, geram pedidos duplicados.
- Processos noturnos que congestionam integrações e relatórios.
Backoff exponencial com jitter: parâmetros e exemplo
Retries simples em intervalos fixos amplificam congestionamento. Use backoff exponencial com jitter para espaçar tentativas e evitar rajadas sincronizadas. A cada falha, o tempo de espera cresce, e um ruído aleatório (jitter) dispersa as tentativas.
Parâmetros práticos para configurar: tentativas máximas, fator de crescimento, limite superior, jitter (full ou equal) e deadline total da operação. Respeite o rate limit do marketplace e aborte com erro claro quando o deadline expirar.
Referências úteis: Exponential Backoff and Jitter (AWS) e Guidance de backoff (Google Cloud).
- Max attempts: define teto para falhas reais.
- Base delay e fator: por exemplo, 200 ms e fator 2.
- Max backoff: evita esperas excessivas.
- Jitter: "full" reduz sincronização entre clientes.
- Deadline total: cancele se o tempo de negócio estourar.
function retryWithExponentialBackoff(op, isRetryable, maxAttempts=6,
base=0.2s, factor=2, maxDelay=10s,
jitter='full', deadline=30s) {
start = now()
attempt = 1
while (true) {
try {
return op()
} catch (err) {
if (attempt >= maxAttempts || !isRetryable(err)) throw err
elapsed = now() - start
if (elapsed > deadline) throw DeadlineExceeded
// Exponential delay
delay = min(maxDelay, base * (factor ** (attempt - 1)))
// Jitter
if (jitter == 'full') delay = random(0, delay)
if (jitter == 'equal') delay = (delay / 2) + random(0, delay / 2)
sleep(delay)
attempt++
}
}
}
Idempotência: evitando pedidos e atualizações duplicadas
Retries só são seguros com operações idempotentes. Para POSTs, gere uma chave de idempotência por pedido/entidade e persista o resultado associado. Assim, reenvios retornam o mesmo efeito sem duplicar.
Projete o ERP para registrar processamentos com chaves únicas e metadados: status final, payload normalizado, horário e TTL opcional quando cabível. Nunca reenvie POST sem idempotência.
Para fluxo assíncrono, use filas e controle de deduplicação. Entenda trade-offs de entrega eventual e chaves idempotentes em entrega eventual ERP–loja virtual.
- Defina escopo da chave: por pedido, item, nota, ou operação.
- Armazene hash do payload para detectar diferenças sutis.
- Retorne 200/201 com o mesmo body quando reprocessar.
- Faça expiração de chaves quando o domínio permitir.
- Inclua a chave em logs e métricas para rastreio.
Circuit breaker na prática: estados, limiares e fallback
Circuit breaker evita sobrecarregar serviços instáveis. Estados: fechado (normal), aberto (bloqueia chamadas) e half‑open (testes limitados). Ele abre ao detectar taxa de falha alta em janela deslizante.
Defina limiares claros: taxa de erro, timeouts sucessivos, volume mínimo e duração de abertura. Planeje fallback específico para cada operação crítica.
Estratégias comuns: enfileirar para reprocesso, servir cache recente, ou degradar funcionalmente (ex.: pausar atualização de fotos, manter preço/estoque).
- Janela deslizante com N chamadas mínimas para estatística.
- Erro composto: 5xx, timeouts e 429 contam, 4xx de validação não.
- Half‑open com poucas tentativas e espaçamento maior.
- Backoff para reabrir após período de resfriamento.
- Exponha estado do breaker em métricas e healthchecks.
class CircuitBreaker {
state = 'CLOSED'
openedAt = null
failureCount = 0
successCount = 0
function call(fn, isRetryable) {
if (this.state == 'OPEN') {
if (now() - this.openedAt < cooldown) throw OpenCircuit
this.state = 'HALF_OPEN'
this.failureCount = 0; this.successCount = 0
}
try {
res = retryWithExponentialBackoff(fn, isRetryable)
if (this.state == 'HALF_OPEN') this.successCount++
if (this.successCount >= halfOpenSuccesses) this.close()
return res
} catch (e) {
this.failureCount++
if (this.shouldOpen()) this.open()
throw e
}
}
function shouldOpen() { return this.failureRate() > threshold && this.sampleSize() >= minSamples }
function open() { this.state = 'OPEN'; this.openedAt = now() }
function close() { this.state = 'CLOSED'; this.failureCount = 0; this.successCount = 0 }
}
Qual erro merece retry? Tabela de decisão
Nem todo erro deve ser retentado. Classifique primeiro. Abaixo, um mapa prático para integrações ERP–marketplaces. Ajuste conforme políticas de cada API e contrato de negócio.
| Categoria de erro | Exemplos | Retentar? | Estratégia recomendada |
|---|---|---|---|
| Rate limit | 429, headers Retry-After | Sim | Backoff exponencial com jitter respeitando Retry-After; registrar métrica de saturação |
| Falha transitória do provedor | 5xx, timeout, DNS | Sim | Retries com deadline; envolver com circuit breaker |
| Conflito/reprocesso | 409, recurso já existe | Depende | Verificar idempotência; recuperar estado e prosseguir |
| Erro de validação | 400, schema inválido | Não | Corrigir payload; criar alerta e dead-letter |
| Autenticação/autorização | 401/403 | Não | Renovar credenciais; bloquear fluxo até resolver |
| Negócio (regra) | 422, limite tributário | Não | Tratamento no ERP; fila de revisão manual |
| Incerteza de status | Timeout após POST | Sim (idempotente) | Repetir com mesma chave; se exceder, consultar recurso antes de novo envio |
Observabilidade: métricas, logs estruturados e correlação
Sem visibilidade, retries viram caixa‑preta. Instrumente cada integração com métricas, logs e traços. Use correlação para seguir uma requisição ponta a ponta, do ERP ao marketplace.
Estruture logs em JSON, com chave de idempotência, correlação, tentativas, delays e estado do breaker. Veja como padronizar em logs estruturados e correlação e centralizar com Fluentd + Elasticsearch.
- Métricas: tentativas, sucesso por operação, erros por categoria.
- Histogramas de delay e latência end‑to‑end.
- Gauges: estado do breaker e duração aberto.
- Alertas por taxa de erro e saturação de rate limit.
- Dashboards por marketplace, operação e conta.
Testes, simulação de falhas e rollout seguro
Teste retries e breaker sob falhas reais. Simule 429, 5xx, timeouts, jitter extremo e lentidão controlada. Valide que o sistema não duplica pedidos e respeita deadlines de negócio.
Implemente rollout progressivo: flags por marketplace/operação, métricas comparativas e reversão simples. Em sistemas legados, flags ajudam a ativar por conta ou rota. Veja práticas em feature flags em monólitos PHP.
- Ambiente de sandbox do marketplace sempre que possível.
- Testes de carga focados em picos e janelas fiscais.
- Fault injection: derrubar DNS simulado e variar latência.
- Canary por percentuais de contas/lojas.
- Runbook de incidentes com passos e contatos.
Perguntas frequentes
Como decidir o número de tentativas e o intervalo do backoff?
Baseie-se na SLO da operação e nos limites do marketplace. Use poucas tentativas com backoff exponencial e jitter, limite superior de espera e deadline total. Se a janela de negócio é curta, prefira menos tentativas e fallback rápido para fila ou revisão.
Circuit breaker não esconde problemas do time?
Não, ele evita colapsos enquanto sinaliza o risco. Exponha métricas de estado, taxa de falhas e razão de abertura. Gere alertas claros para que o time atue na causa raiz. Breaker é contenção, não correção definitiva.
Como evitar duplicações ao repetir POSTs?
Implemente idempotência: gere uma chave por operação de negócio, persista resultado e responda consistentemente em reenvios. Em incerteza de status (timeout), repita com a mesma chave ou faça leitura por referência antes de reenviar. Sem idempotência, não faça retry de POST.
Devo sempre usar fila com retries e circuit breaker?
Não sempre. Fila é útil para desacoplar picos e reprocessar com controle, mas adiciona complexidade. Em integrações críticas ou de alto volume, filas ajudam. Avalie prazos, volume e SLAs do marketplace para decidir o acoplamento e padrões de reprocesso.
Quando parar de tentar e gerar erro para o usuário ou operador?
Pare quando o deadline de negócio for atingido, o número máximo de tentativas estourar ou o breaker abrir. Registre o motivo, alimente uma fila de revisão se aplicável e notifique o operador com dados para ação (erro categorizado, operação e marketplace).
Precisando revisar a resiliência das suas integrações?
Se você quer aplicar retries com backoff, idempotência e circuit breaker sem arriscar duplicações ou paralisações, vamos conversar sobre seu cenário e próximos passos.
Falar sobre integrações resilientesVeja também
- Guia prático: como configurar failover ativo-passivo entre duas VPS com Keepalived, HAProxy e lsyncd para uploads sincronizados
- Guia: checklist técnico para preparar VPS Debian com Docker Compose para aplicações PHP em produção
- Guia prático para dimensionamento de VPS e tuning de PHP‑FPM para lojas Magento/OpenMage com picos sazonais: do sizing ao teste de carga
- Guia: como planejar e executar testes de carga em aplicações PHP monolito usando k6 e Docker Compose — passo a passo