Promise.allSettled vs Promise.all for a batch of API jobs

Promise.allSettled waits for every promise and reports each outcome; Promise.all rejects on the first failure. For paid API jobs, use allSettled.

5 min readSume
All posts

Promise.allSettled() takes an array of promises and fulfills once every one has settled, with one { status, value } or { status, reason } object per promise, in input order. Promise.all() rejects as soon as any promise rejects and gives you only that first error. Use allSettled when each task stands on its own and you need every result, which is the case when you submit a batch of paid API jobs: one failed submit must not hide the job ids of the ones that succeeded.

JavaScript facts come from MDN's Promise.allSettled() and Promise.all() pages. The job API is Sume's, from Jobs and results, Video Generation and the API reference, all read on 2026-09-29.

What is the difference between Promise.all and Promise.allSettled?

MDN puts it plainly: use allSettled() if you need the final result of every promise; all() may fit better when the tasks depend on each other or when you want to reject immediately on any failure.

From MDN's Promise.allSettled() and Promise.all(), read 2026-09-29.
`Promise.all()``Promise.allSettled()`
Fulfills whenEvery input fulfillsEvery input settles, fulfilled or rejected
Rejects whenAny input rejects, with the first reasonNot on an input's rejection; it waits for every input
ResultArray of valuesArray of { status, value } or { status, reason }, in input order
Other promises after a failureNot canceled; later rejections are ignoredAwaited to the end

Why is Promise.all risky for paid API jobs?

Because a rejection doesn't stop anything. MDN notes that rejecting the returned promise does not cancel the remaining operations. The other requests are already on the wire; the ones the server accepts become jobs that run and bill, while your catch block holds a single error and none of their ids.

On Sume, every submit returns the job id in its first response, and a 2xx means the job exists and paid work is in flight. A client-side timeout does not cancel a job: it keeps running and still bills. Cancel works only before generation starts; after that the API answers 409 job_generation_already_started. So the useful move is to keep every id, not to abort the batch.

How do I handle errors with Promise.allSettled?

Map each input to a submit, then split the outcomes. Give each item an Idempotency-Key built from the item, so the retry of a rejected submit sends the same key. That matters when a submit rejected with a network error: the server may have created the job anyway, and on POST /v1/videos a replay with the same key returns the original job instead of a second one.

async function submit(item) {
  const res = await fetch("https://api.sume.com/v1/videos", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SUME_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": `clip-${item.id}-v1`, // same key on every retry
    },
    body: JSON.stringify({ model: "sume/auto", prompt: item.prompt, aspect_ratio: "9:16", duration: 5 }),
  });
  const body = await res.json().catch(() => ({}));
  if (!res.ok) throw Object.assign(new Error(body.error?.code ?? `HTTP ${res.status}`), { status: res.status });
  return body; // 202: { id, polling_url, status }
}

const results = await Promise.allSettled(items.map(submit));
const accepted = [];
const failed = [];
results.forEach((r, i) => {
  if (r.status === "fulfilled") accepted.push({ item: items[i].id, job: r.value.id });
  else failed.push({ item: items[i], error: r.reason });
});
await saveJobIds(accepted); // store before anything else
// retry only failed items, with their same keys, after reading each error

Does Promise.allSettled limit how many requests run at once?

No. items.map(submit) starts every request before allSettled is even called; it only collects the outcomes. A large batch sent this way spends the key's per-minute write budget in one burst, and on Sume it can also fill the workspace's accepted-job capacity, after which submits fail with 429 queue_full. In current code a same-key retry of a queue_full submit replays that refusal, so once jobs finish, resend those items with a new key. Cap the batch with p-limit and see video job concurrency and queueing for the numbers.

What if my process crashes before it saves the ids?

GET /v1/jobs lists jobs, filterable by status and type, so a restart can find what the lost batch created. List jobs and recover lost job ids shows how to page through them. Then poll each accepted job with backoff until its status is terminal; don't resubmit a paid request because a local process died.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume