DEV Community

Coditi Team
Coditi Team

Posted on

Why Promise.all() Almost Broke Our Order Pipeline

We had a bug that only showed up when a third-party service went down — not our code. That's always a fun one to debug.

The setup

On every order, our API kicked off five async tasks in parallel:

await Promise.all([
  sendConfirmationEmail(order),
  updateInventory(order),
  generateInvoice(order),
  notifyWarehouse(order),
  createAuditLog(order),
]);
Enter fullscreen mode Exit fullscreen mode

Simple, readable, and totally wrong for this use case — we just didn't know it yet.

The failure mode

Promise.all() short-circuits: the instant any promise rejects, it rejects immediately and the rest are left dangling. So when our email provider had a temporary outage, this happened:

  • ❌ Inventory update — never ran
  • ❌ Warehouse notification — never ran
  • ❌ Audit log — never ran

Meanwhile, the order was already confirmed and paid for. The customer just saw... nothing. No inventory change, no warehouse ping, no trace in the audit log. One unrelated service failure took down four unrelated tasks.

comparison_diagram

The fix: Promise.allSettled()

const results = await Promise.allSettled([
  sendConfirmationEmail(order),
  updateInventory(order),
  generateInvoice(order),
  notifyWarehouse(order),
  createAuditLog(order),
]);

const failed = results.filter(
  result => result.status === "rejected"
);

// handle/retry `failed` independently
Enter fullscreen mode Exit fullscreen mode

allSettled() always resolves once every promise finishes, giving you a status of "fulfilled" or "rejected" for each one. No more all-or-nothing behavior.

Result:

  • ✅ Inventory still updates
  • ✅ Warehouse still gets notified
  • ✅ Audit logs still get written
  • ✅ Only the failed task gets queued for retry

Takeaway

Promise.all() is great when every task genuinely depends on all the others succeeding. But for independent side effects — email, logging, notifications — allSettled() is almost always the safer default. One flaky dependency shouldn't get veto power over four healthy ones.

Curious — have you been bitten by this before? Where else have you seen Promise.all() used when allSettled() should've been the call?

Top comments (1)

Collapse
 
topstar_ai profile image
Luis Cruz

I've encountered similar issues with Promise.all() in the past, particularly when dealing with third-party services that can be unreliable. The author's point about using Promise.allSettled() for independent side effects is well-taken, as it allows for more granular error handling and prevents a single failure from bringing down the entire pipeline. One potential improvement to the allSettled() approach could be to implement a retry mechanism for failed tasks, using a library like retry-async to handle exponential backoff and retries. Have you considered adding such a mechanism to your order pipeline to further improve resilience?