Parallel vs sequential data fetching in Next.js comes down to total wait time. Sequential fetching waits for one request to finish before starting the next, so the times add up. Parallel fetching starts every request at once, so the page waits only for the slowest one.
In a Server Component you choose the pattern yourself, because nothing reorders your awaits for you.
// app/posts/page.tsx
export default async function PostsPage() {
const postsRes = await fetch("https://api.example.com/posts");
const posts = await postsRes.json();
const authorsRes = await fetch("https://api.example.com/authors");
const authors = await authorsRes.json();
return <p>{posts.length} posts, {authors.length} authors</p>;
}Each fetch blocks the next one. If posts takes 300ms and authors takes 400ms, the page waits about 700ms before anything renders.
// app/posts/page.tsx
export default async function PostsPage() {
const [postsRes, authorsRes] = await Promise.all([
fetch("https://api.example.com/posts"),
fetch("https://api.example.com/authors"),
]);
const posts = await postsRes.json();
const authors = await authorsRes.json();
return <p>{posts.length} posts, {authors.length} authors</p>;
}Both requests start at the same time, so the page now waits about 400ms, the slower of the two, instead of 700ms.
When to fetch sequentially
Use sequential fetching when one request depends on the previous result, such as fetching a user id first and then that user's posts. There is no way to parallelize a dependency, and trying to do so just adds complexity.
A common example is fetching a list of posts, then fetching each post's author. The second step needs the post ids from the first, so no amount of parallelization removes the second round trip. Think of sequential fetching as a dependency chain rather than a performance choice.
When to fetch in parallel
Use parallel fetching when the requests are independent. A page that shows posts and authors together does not need one before the other, so Promise.all cuts the wait to the slowest request.
Promise.all rejects as soon as one promise rejects, so a failed independent request still fails the whole page unless you handle errors per request. When the requests hit the same origin, this is usually a safe win with no downside, and it matters most when each request is slow on its own.
- Independent requests: fetch in parallel with Promise.all.
- Dependent requests: fetch sequentially with await.
A mixed approach
Real pages often mix both patterns. Fetch the independent requests together with Promise.all, then use one of those results to fetch the next dependent piece. That keeps the independent work parallel without pretending a dependency can be skipped.
The choice also affects loading states. A parallel page waits once for the combined result, while a sequential page can reveal the first result before the second request finishes.
Duplicate requests are a separate concern
Next.js memoizes identical GET fetch calls within one render pass, so two components that fetch the same URL do not double the work. That applies to fetch specifically, so an ORM or axios call is not deduplicated the same way.
Deduplication is about repeated requests, not about ordering, so it never turns a sequential chain into a parallel one. For the full detail, see request deduplication vs React cache. For the basics of fetching inside a Server Component, see data fetching in Server Components.
Rune AI
Key Insights
- Sequential fetching waits for each request in turn.
- Parallel fetching with Promise.all waits only for the slowest request.
- Use Promise.all for independent requests.
- Use sequential await when one request depends on another.
- Promise.all rejects on the first failure.
Frequently Asked Questions
Which is faster, parallel or sequential?
Does Promise.all fail if one request fails?
Does Next.js fetch these requests in parallel for me?
Conclusion
Sequential fetching adds request times, while parallel fetching waits only for the slowest one. Fetch in parallel when requests are independent, and fetch sequentially only when a later request needs an earlier result.
More in this topic
`generateMetadata` Explained with Real Examples
What generateMetadata does, when it runs, and how to use it for real routes: awaited params, deduplicated data fetching, extending parent metadata, and returning a 404 from metadata.
Canonical URLs in Next.js: `metadataBase`, `alternates.canonical`, and Dynamic Pages
How canonical URLs work in the Next.js App Router: setting metadataBase once, writing alternates.canonical per route, handling dynamic segments, and what happens when the base URL is missing.
Open Graph and Twitter Card Metadata in Next.js
How to write Open Graph and Twitter card metadata in the Next.js App Router: the openGraph and twitter fields, automatic card defaults, article tags, and image merge rules.