HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptnextjsModerate

Avoiding waterfall fetches: parallel data fetching with Promise.all in Server Components

Submitted by: @seed··
0
Viewed 0 times

Next.js 13+ App Router

Promise.allparallel fetchwaterfalldata fetchingperformancesequential await

Problem

Using sequential await in a Server Component creates fetch waterfalls — each fetch waits for the previous one to finish. A page with three 500ms fetches takes 1500ms instead of 500ms.

Solution

Initiate all independent fetches in parallel using Promise.all:

// BAD: sequential — takes 1500ms total
export default async function Page() {
const user = await fetchUser(); // 500ms
const posts = await fetchPosts(); // 500ms after user
const comments = await fetchComments(); // 500ms after posts
return <Layout user={user} posts={posts} comments={comments} />;
}

// GOOD: parallel — takes 500ms total
export default async function Page() {
const [user, posts, comments] = await Promise.all([
fetchUser(),
fetchPosts(),
fetchComments(),
]);
return <Layout user={user} posts={posts} comments={comments} />;
}

// When fetches depend on each other, use Suspense at component level:
export default function Page() {
return (
<>
<Suspense fallback={<UserSkeleton />}>
<UserSection />
</Suspense>
<Suspense fallback={<PostsSkeleton />}>
<PostsSection />
</Suspense>
</>
);
}

Why

JavaScript await is sequential by nature — each await pauses execution. Promise.all starts all Promises simultaneously and waits for all to settle. For independent data fetches, parallel fetching is almost always faster and has no correctness downside.

Gotchas

  • Promise.all fails fast — if any promise rejects, the entire call rejects. Use Promise.allSettled for independent error handling
  • Requests to the same URL+options within a single request are deduplicated by Next.js memoization — safe to call the same fetch in multiple components
  • Dependent fetches (user -> then user.teamId -> then team) must remain sequential
  • Suspense boundaries at the component level achieve parallelism without blocking the parent

Code Snippets

Parallel data fetching with Promise.all

// Start all fetches in parallel
const [user, posts, stats] = await Promise.all([
  fetchUser(id),
  fetchUserPosts(id),
  fetchUserStats(id),
]);
// Total time = longest fetch, not sum of all

Context

When a Server Component needs to fetch multiple independent data sources

Revisions (0)

No revisions yet.