Async/Await Pitfalls: Parallel vs Sequential (With Examples)

Interview-focused async/await guide: how await works, common mistakes, parallelizing with Promise.all, error handling patterns, and when to avoid await-in-loop.

F

Frontend Interview Team

February 08, 2026

~12 min
Async/Await Pitfalls: Parallel vs Sequential (With Examples)

async/await makes async code look synchronous. That’s great for readability, but it also makes it easy to accidentally slow down your code.

This post is mainly about one interview-critical topic:

Parallel vs sequential execution

30‑second interview answer

await pauses the current async function until a promise settles. If you await tasks one after another, you make them sequential (slower). To run independent tasks in parallel, start them first and then await Promise.all(...). For loops, avoid await inside a loop unless you need sequential behavior.

Key points

  • await resumes later (as a microtask continuation).
  • Sequential awaits add latencies.
  • Use Promise.all for parallel work.
  • Use allSettled if you want partial success.

1) What await actually does

When you write:

const data = await fetch('/api');

You’re saying:

  • pause this async function
  • resume later when the promise settles

While it’s paused, the JS thread can run other tasks.


2) The most common mistake: sequential awaits

Bad (sequential)

const user = await fetch('/api/user').then(r => r.json());
const posts = await fetch('/api/posts').then(r => r.json());

This waits for user to finish before starting posts.

Good (parallel)

const [userRes, postsRes] = await Promise.all([
  fetch('/api/user'),
  fetch('/api/posts'),
]);
 
const [user, posts] = await Promise.all([
  userRes.json(),
  postsRes.json(),
]);

3) await inside loops (another interview trap)

Bad

for (const id of ids) {
  const item = await fetch(`/api/items/${id}`).then(r => r.json());
  results.push(item);
}

This runs requests one by one.

Better (parallel)

const results = await Promise.all(
  ids.map((id) => fetch(`/api/items/${id}`).then(r => r.json()))
);

When sequential is correct

Sometimes you must do sequential, for example:

  • the next request depends on the previous result
  • you need to respect rate limits

In interviews, say this explicitly.


4) Error handling patterns

Pattern A: one try/catch

try {
  const data = await doWork();
  return data;
} catch (err) {
  // handle / log
  throw err;
}

Pattern B: partial success

If you want partial results:

const results = await Promise.allSettled(tasks);
const ok = results
  .filter(r => r.status === 'fulfilled')
  .map(r => r.value);

5) Interview Q: “Does await make code parallel?”

No.

  • await pauses the function.
  • Whether work runs in parallel depends on whether you started promises concurrently.

Correct answer:

  • Start promises first
  • then await them together with Promise.all

Summary checklist

  • I can explain sequential vs parallel async.
  • I know why await in a loop can be slow.
  • I default to Promise.all for independent tasks.
  • I know when to use allSettled.

Summary

  • await can accidentally serialize your async work.
  • Use Promise.all to parallelize independent tasks.
  • Avoid await in loops unless you truly need sequential behavior.
  • Use allSettled when partial success is acceptable.