JavaScript
async/await
fetch API
asynchronous programming
web development

What is the difference between async await and a regular fetch?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

fetch() and async or await are related, but they are not alternatives to each other. fetch() is the API that starts an HTTP request and returns a promise, while async and await are language features for writing promise-based code in a more readable way.

fetch() Is Already Asynchronous

Calling fetch() does not block the browser while the network request runs. It immediately returns a promise, and you can attach handlers with .then() and .catch().

javascript
1fetch("/api/users/42")
2  .then((response) => {
3    if (!response.ok) {
4      throw new Error("Request failed");
5    }
6    return response.json();
7  })
8  .then((user) => {
9    console.log(user.name);
10  })
11  .catch((error) => {
12    console.error(error.message);
13  });

This is often called promise chaining. It is a perfectly normal way to work with fetch().

await Changes the Style of Promise Handling

await can be used only inside an async function or supported module scope. It pauses that async function until the awaited promise settles, then resumes execution with the resolved value or throws the rejection as an exception.

javascript
1async function loadUser() {
2  try {
3    const response = await fetch("/api/users/42");
4
5    if (!response.ok) {
6      throw new Error("Request failed");
7    }
8
9    const user = await response.json();
10    console.log(user.name);
11  } catch (error) {
12    console.error(error.message);
13  }
14}
15
16loadUser();

Under the hood, this is still promise-based code. await fetch(...) does not create a different kind of request. It just gives you a syntax that reads more like straight-line control flow.

The Main Difference Is Readability and Control Flow

The promise-chain version and the async or await version are both asynchronous and both use promises. The difference is mostly how the code is expressed.

Promise chaining is often fine when:

  • the flow is short
  • each step naturally follows from the previous one
  • you already have helper functions that return promises

async or await tends to be clearer when:

  • you have several steps in sequence
  • you want try or catch style error handling
  • you mix conditionals, loops, and asynchronous work

For example, a sequential loop is easier to read with await:

javascript
1async function loadUsers(ids) {
2  for (const id of ids) {
3    const response = await fetch(`/api/users/${id}`);
4    const user = await response.json();
5    console.log(user.name);
6  }
7}

That is possible with chained promises too, but it becomes harder to scan once the control flow is more complex.

await Does Not Automatically Mean Better Performance

One common misunderstanding is that await is somehow a "more asynchronous" version of fetch(). It is not. In fact, sequential await calls can be slower than necessary if the requests could have run together.

For parallel requests, use Promise.all:

javascript
1async function loadUsers(ids) {
2    const responses = await Promise.all(
3      ids.map((id) => fetch(`/api/users/${id}`))
4    );
5
6    const users = await Promise.all(
7      responses.map((response) => response.json())
8    );
9
10    console.log(users.map((user) => user.name));
11}

This is still async or await, but it preserves concurrency instead of forcing one request to finish before the next starts.

Common Pitfalls

  • Thinking fetch() and async or await solve the same problem. They do not.
  • Assuming await fetch(...) blocks the whole JavaScript runtime. It pauses only the surrounding async function.
  • Forgetting that fetch() resolves even for HTTP errors such as 404, so response.ok still needs checking.
  • Writing sequential await calls when the requests could have run in parallel with Promise.all.
  • Mixing .then() and await in the same flow without a clear reason, which often makes the code harder to follow.

Summary

  • 'fetch() is the HTTP request API and returns a promise.'
  • 'async and await are JavaScript syntax for working with promises, including fetch promises.'
  • Both promise chaining and await are asynchronous; the main difference is readability and control flow.
  • 'await is often easier for multi-step logic and error handling.'
  • For concurrent requests, combine fetch() with Promise.all instead of awaiting each request one by one.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.