patternjavascriptMajor
Graceful degradation: returning partial results when dependencies fail
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.