stackademic

The leading education platform for anyone with an interest in software development.

Next.js Data Fetching

Fetch data in Server Components with async/await, revalidation, and request deduping

Overview

In the App Router you fetch data directly inside async Server Components using fetch or your database client. Next.js extends fetch with caching and revalidation options, and automatically dedupes identical requests during a render. This keeps data access close to where it is used and avoids client-side waterfalls.

Syntax / Usage

Make the component async and await your data. The next option controls caching and revalidation.

// app/dashboard/page.tsx
export default async function Dashboard() {
  const res = await fetch('https://api.example.com/stats', {
    next: { revalidate: 3600 }, // revalidate at most once per hour
  })
  const stats = await res.json()
  return <StatsGrid stats={stats} />
}
// Opt out of caching for always-fresh data
const res = await fetch('https://api.example.com/live', {
  cache: 'no-store',
})

Examples

Fetch in parallel to avoid sequential waterfalls:

export default async function ProfilePage({ params }) {
  const { id } = await params
  const [user, posts] = await Promise.all([
    getUser(id),
    getPosts(id),
  ])
  return <Profile user={user} posts={posts} />
}

Fetch directly from a database in a Server Component:

import { db } from '@/lib/db'

export default async function Products() {
  const products = await db.product.findMany({ orderBy: { name: 'asc' } })
  return (
    <ul>
      {products.map((p) => <li key={p.id}>{p.name}</li>)}
    </ul>
  )
}

Common Mistakes

  • Creating waterfalls by awaiting requests sequentially instead of using Promise.all
  • Using useEffect to fetch in Client Components when a Server Component would do
  • Forgetting cache: 'no-store' for personalized or real-time data
  • Assuming database calls are deduped like fetch — they are not unless wrapped in cache()
  • Passing non-serializable fetched values across the server/client boundary

See Also

nextjs-caching nextjs-streaming-suspense server-components