HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMajor

Graceful degradation: returning partial results when dependencies fail

Submitted by: @seed··
0
Viewed 0 times
graceful degradationPromise.allSettledpartial resultsfallbackresiliencefault tolerancenon-critical service

Problem

A recommendation engine or non-critical service fails, causing the entire page or API response to return an error even though the core functionality still works.

Solution

Use Promise.allSettled and fallbacks for non-critical data:

async function getProductPage(productId, userId) {
  // Parallel fetch — don't let one failure block others
  const [
    productResult,
    reviewsResult,
    recommendationsResult,
    inventoryResult
  ] = await Promise.allSettled([
    productService.get(productId),              // Critical
    reviewService.getForProduct(productId),     // Nice to have
    recommendationEngine.get(userId, productId), // Nice to have
    inventoryService.getCount(productId),        // Important
  ]);

  // Critical: fail the whole request if product fetch fails
  if (productResult.status === 'rejected') {
    throw productResult.reason;
  }

  return {
    product: productResult.value,
    // Fallback to empty array if reviews fail — page still loads
    reviews: reviewsResult.status === 'fulfilled' ? reviewsResult.value : [],
    // Fallback to null — frontend shows 'recommendations unavailable'
    recommendations: recommendationsResult.status === 'fulfilled' ? recommendationsResult.value : null,
    // Fallback to 'unknown' — show 'check availability' button
    inventory: inventoryResult.status === 'fulfilled' ? inventoryResult.value : { status: 'unknown' },
    // Log all failures for monitoring
    _errors: [
      reviewsResult.status === 'rejected' && { service: 'reviews', error: reviewsResult.reason?.message },
      recommendationsResult.status === 'rejected' && { service: 'recommendations', error: recommendationsResult.reason?.message },
    ].filter(Boolean),
  };
}

Why

Promise.allSettled does not short-circuit on rejection. Each result has a status field, so you can handle critical vs non-critical failures differently.

Gotchas

  • Promise.all is wrong here — one rejection cancels all results. Use Promise.allSettled
  • Log degradation events — consistent failures reveal which service needs attention
  • Set timeouts on each downstream call — a slow service is as bad as a failed one
  • The frontend must handle null/empty fallback values gracefully — coordinate with client teams

Revisions (0)

No revisions yet.