Improve API Fault Tolerance with Promise.allSettled

Concurrent API fetching is a standard requirement in modern web applications, but network instability and failing third-party services can easily disrupt data aggregation. While traditional approaches like Promise.all immediately fail if even a single request is rejected, JavaScript's Promise.allSettled ensures all asynchronous operations run to completion regardless of their individual outcomes. This article explains how Promise.allSettled enhances fault tolerance by preventing single points of failure, enabling graceful UI degradation, and simplifying error recovery when fetching data from multiple endpoints simultaneously.

The Limitation of Traditional Concurrent Fetching

When coordinating multiple network requests simultaneously, developers often turn to Promise.all. However, Promise.all implements a "fail-fast" mechanism: if any single promise rejects, the entire aggregate promise immediately rejects.

In a scenario where an application requests user profile data, notification counts, and analytics metrics concurrently, an outage in the analytics service will cause Promise.all to drop the entire payload. The application loses access to the valid, successfully returned user profile and notification data, leaving the user with an empty screen or an unnecessary fatal error state.

How Promise.allSettled Enhances Fault Tolerance

Introduced in ECMAScript 2020, Promise.allSettled accepts an iterable of promises and resolves only after all the given promises have either fulfilled or rejected. Unlike Promise.all, it never short-circuits on failure.

Instead of returning a single aggregated array of results or throwing a single error, Promise.allSettled resolves to an array of outcome objects. Each object describes the result of each individual promise:

  • Fulfilled promises return { status: 'fulfilled', value: data }
  • Rejected promises return { status: 'rejected', reason: error }

This shift in execution provides three primary architectural benefits for fault tolerance:

1. Graceful Degradation of User Interfaces

Modern web interfaces often resemble dashboards composed of discrete widgets or independent modules. By using Promise.allSettled, an application can inspect each result independently. If the API providing promotional banners fails, the application can safely render the core content, product listings, and navigation items while displaying an unobtrusive fallback state or placeholder for the failed banner.

2. Comprehensive Error Logging and Auditing

Under the Promise.all model, only the first rejection is caught; all subsequent failures are ignored or swallowed. Promise.allSettled preserves the outcome of every request in the batch. This allows monitoring tools to log the exact set of failing endpoints across a single user interaction, providing clear insights into systemic service degradations versus isolated client-side errors.

3. Simplified Partial-Success Handling

Handling partial successes with Promise.all typically requires wrapping every individual fetch call in a custom .catch() handler to normalize rejections into resolved values. Promise.allSettled standardizes this behavior natively. Developers can process the final array using standard array methods to separate successes from failures:

const results = await Promise.allSettled([
  fetchUserData(),
  fetchNotifications(),
  fetchAnalytics()
]);

const successfulData = results
  .filter((res) => res.status === 'fulfilled')
  .map((res) => res.value);

const errors = results
  .filter((res) => res.status === 'rejected')
  .map((res) => res.reason);

Ideal Use Cases

Promise.allSettled is best suited for non-dependent concurrent tasks where partial data is preferable to no data:

  • Composite Dashboards: Pages pulling data from multiple independent microservices.
  • Batch Operations: Submitting multiple forms, sending bulk emails, or uploading several files where failures should be flagged individually without halting the rest of the queue.
  • Health Checks and Monitoring: Pinging multiple third-party integrations to report on overall service health.

By preventing isolated network issues from invalidating an entire batch of requests, Promise.allSettled provides a robust, native foundation for resilient data-fetching strategies in distributed web environments.