Fallback
O problema no contexto distribuído
Seção intitulada “O problema no contexto distribuído”Falhas parciais são inevitáveis: um serviço de recomendações caiu, o de preços está lento, o Circuit Breaker abriu. Sem tratamento, essa falha sobe até o usuário como um erro 500, mesmo que a funcionalidade principal ainda funcione. Muitas vezes a dependência é não-crítica — a página de produto pode ser renderizada sem o bloco de “recomendados”. O fallback decide o que servir quando o caminho feliz não está disponível.
A solução
Seção intitulada “A solução”Definir, para cada chamada que pode falhar, uma resposta alternativa invocada quando a chamada principal lança exceção ou é barrada pelo circuit breaker. Estratégias comuns, da melhor à mais pobre:
- Cache: retornar o último valor conhecido (stale-but-usable). Ideal para dados que mudam pouco.
- Valor default / vazio: lista de recomendações vazia, frete “a calcular”, flag desligada.
- Funcionalidade reduzida: servir uma versão simplificada (ex.: busca sem ranking personalizado).
- Fonte secundária: um serviço/replica alternativo.
- Falha explícita e honesta: quando não há alternativa segura, uma mensagem clara (“recomendações indisponíveis”) é melhor que dados errados.
Critério: criticidade da dependência
Seção intitulada “Critério: criticidade da dependência”O fallback só faz sentido para dependências não-críticas ao caso de uso. Para uma dependência crítica (ex.: autorização de pagamento numa compra), não invente um fallback que finja sucesso — falhe de forma segura. Servir dado errado pode ser pior que servir erro.
Trade-offs
Seção intitulada “Trade-offs”- Prós: mantém disponibilidade percebida, isola falhas de dependências não-críticas, melhora a experiência.
- Contras: pode servir dados desatualizados (cache stale) e mascarar problemas reais (o incidente fica invisível se o fallback for silencioso). Fallbacks precisam de observabilidade — métricas/logs de quantas vezes foram acionados.
Quando NÃO usar
Seção intitulada “Quando NÃO usar”- Em dependências críticas onde uma resposta falsa é perigosa (pagamento, autorização, saldo).
- Quando não existe alternativa segura e significativa — melhor falhar explicitamente.
- Quando o fallback esconde falhas que precisam de ação imediata sem gerar alertas.
Exemplo Java/Spring com Resilience4j
Seção intitulada “Exemplo Java/Spring com Resilience4j”Fallback combinado com Circuit Breaker: quando o circuito abre ou a chamada falha, serve cache; se não houver cache, lista vazia.
@Service@RequiredArgsConstructorpublic class RecommendationService {
private final RecommendationClient client; private final RecommendationCache cache;
@CircuitBreaker(name = "recommendations", fallbackMethod = "fromCacheOrEmpty") public List<Product> recommend(UUID userId) { var result = client.fetchRecommendations(userId); cache.put(userId, result); return result; }
private List<Product> fromCacheOrEmpty(UUID userId, Throwable ex) { log.warn("Fallback de recomendações para user={} causa={}", userId, ex.toString()); recommendationFallbackCounter.increment(); return cache.get(userId).orElseGet(List::of); }}A assinatura do fallbackMethod deve casar com o método original mais o Throwable no fim. Note o incremento de uma métrica: o fallback é observável, não silencioso.
sequenceDiagram
participant UI as Página de Produto
participant Svc as RecommendationService
participant Rec as Serviço de Recomendações
participant Cache
UI->>Svc: recommend(userId)
Svc->>Rec: fetchRecommendations(userId)
Rec-->>Svc: erro / timeout (circuito aberto)
Note over Svc: aciona fallbackMethod
Svc->>Cache: get(userId)
Cache-->>Svc: último valor conhecido (ou vazio)
Svc-->>UI: recomendações degradadas
Note over UI: página renderiza sem erro
Anti-padrões e erros comuns
Seção intitulada “Anti-padrões e erros comuns”- Fallback silencioso: engolir a exceção sem métrica/log — o incidente fica invisível e ninguém corrige a causa.
- Fallback em dependência crítica fingindo sucesso: aprovar um pagamento que na verdade falhou é catastrófico.
- Fallback que também depende do serviço quebrado: cache no mesmo serviço que caiu não ajuda.
- Fallback com lógica pesada que pode falhar por conta própria: mantenha-o simples e rápido.
- Cache stale sem limite de idade: servir dado antigo demais como se fosse atual, sem sinalizar.
Relações
Seção intitulada “Relações”- Par natural do Circuit Breaker: fornece a resposta enquanto o circuito está aberto.
- Complementa Retry: quando os retries esgotam, o fallback assume.
- Protege consultas de API Composition contra falha de uma dependência não-crítica.
- Contexto: Microservices, Sistemas Distribuídos.
- Índice: Microservices Patterns.
Perguntas de revisão
Seção intitulada “Perguntas de revisão”- O que é degradação graciosa e como o fallback a implementa?
Resposta
É manter o sistema utilizável mesmo com partes indisponíveis, oferecendo uma experiência reduzida em vez de um erro total. O fallback a implementa ao substituir a resposta de uma dependência falha por uma alternativa (cache, default, versão simplificada), permitindo que o fluxo principal continue.
- Por que fallbacks não devem ser silenciosos?
Resposta
Porque mascaram o problema real: se o fallback engole a exceção sem métrica nem log, o incidente fica invisível e ninguém corrige a causa raiz. Fallbacks precisam ser observáveis — contadores e alertas — para que a equipe saiba com que frequência estão sendo acionados.
- Em que situação NÃO se deve usar fallback?
Resposta
Em dependências críticas onde uma resposta alternativa seria enganosa ou perigosa — pagamento, autorização, verificação de saldo. Fingir sucesso nesses casos é pior que falhar. Também não se deve usar quando não há alternativa segura e significativa: melhor falhar de forma explícita e honesta.
- Como fallback, retry e circuit breaker se encaixam numa mesma chamada?
Resposta
O Retry tenta absorver falhas transitórias; se persistem, o Circuit Breaker abre e passa a barrar chamadas rapidamente; enquanto o circuito está aberto (ou quando os retries esgotam), o fallback fornece a resposta degradada. Juntos cobrem falha transitória, falha persistente e a experiência do usuário durante a indisponibilidade.