Next.js cookbook · Beginner

Avoid data-fetching waterfalls in Server Components

A dashboard page is slow because it awaits user, stats and notifications one after another.

Approach

Start independent requests at the same time with Promise.all (or start promises early and await them later). Deduplicate repeated reads in one render with React cache(), and push slow, non-critical sections behind Suspense so they stream later.

Solution

import { cache } from "react";
import { Suspense } from "react";

// Deduplicated within a single server render
export const getUser = cache(async (id: string) => db.user.findUnique({ where: { id } }));

export default async function DashboardPage() {
  const session = await verifySession();

  // BUG: Waterfall: ~ t(user) + t(stats) + t(projects)
  // const user = await getUser(session.userId);
  // const stats = await getStats(session.userId);
  // const projects = await getProjects(session.userId);

  // FIX: Parallel: ~ max(t(user), t(stats), t(projects))
  const [user, stats, projects] = await Promise.all([
    getUser(session.userId),
    getStats(session.userId),
    getProjects(session.userId),
  ]);

  return (
    <main>
      <Header user={user} />
      <StatsCards stats={stats} />
      <ProjectList projects={projects} />
      <Suspense fallback={<ActivitySkeleton />}>
        <ActivityFeed userId={session.userId} />     {/* slow, streamed */}
      </Suspense>
    </main>
  );
}

Pitfalls

  • Fetching in nested components that each await before rendering children (component waterfalls).
  • Promise.all failing the whole page for one optional section (use allSettled or Suspense boundaries).
  • Calling your own API routes over HTTP from Server Components.

Variations

  • Preload pattern: call void getUser(id) early in a parent to warm the cache.

Further reading: Next.js: Parallel data fetching

Go deeper: The Browser Side: React and Vue Page Loads in the Request Lifecycle course traces this step of the request, with a production bug and a runnable simulation.

Reference: https://nextjs.org/docs/app/getting-started/fetching-data#parallel-data-fetching

More Next.js recipes