Skip to main content

Fallback

The Fallback pattern supplies an alternative response — cached data, a default, or a secondary provider — when a primary operation fails, keeping features usable under failure. Fallbacks must be monitored and tested, and avoided where correctness cannot be compromised.

Type
Resilience
When to Use
Dependency Failure, Degraded Experience, Default Responses, Cache On Error

When a dependency fails, the simplest behavior is to propagate the error. But for many features a degraded answer is far better than no answer. The Fallback pattern defines an alternative path that executes when the primary operation fails, times out, or is short-circuited by a circuit breaker. Instead of an error page, the user sees cached data, a sensible default, or a reduced-but-functional experience.

How It Works

A fallback wraps a primary call. If the call throws, times out, or is rejected, control passes to the fallback handler, which produces an acceptable substitute. Common fallback sources include:

  • Stale cache: serve the last known good value when the live source is unavailable.
  • Static default: return an empty list, a configured default, or a generic message.
  • Alternative provider: call a secondary service, region, or model.
  • Local computation: compute an approximate result without the failed dependency.

Fallbacks are commonly chained with circuit breakers: when the breaker opens, every call goes straight to the fallback without even attempting the primary, protecting both systems.

When to Use It

Use fallbacks where partial or approximate results are acceptable: recommendations falling back to popular items, personalization falling back to defaults, a pricing service falling back to a cached price, or an AI feature falling back to a smaller model. Avoid fallbacks where correctness is non-negotiable — a payment authorization should fail rather than silently "succeed" via a default.

Trade-offs

Fallbacks can mask outages: if the system always returns stale data smoothly, operators may not notice the primary is down, so fallbacks must be monitored and alerted on. Stale or default data can be wrong in ways that confuse users or violate business rules. A fallback path that is rarely exercised can itself be broken when finally needed, so it should be tested deliberately. Silent fallbacks on writes are especially dangerous.

Related Patterns

Fallback is the action side of circuit-breaker and a building block of graceful-degradation. It often reads from a cache-aside store and follows exhausted retry-with-backoff attempts.

Example

Resilience4j-style fallback:

try:
  return circuitBreaker.run(() -> pricingService.get(id))
catch (CallNotPermitted | Exception e):
  log.warn("pricing fallback", e)
  return priceCache.getOrDefault(id, STANDARD_PRICE)

The user always gets a price; observability flags how often the fallback fires.