Next.js cookbook · Intermediate
Stream slow sections with Suspense
Render the page shell instantly while slow data (recommendations, analytics) loads.
Approach
Fetch fast, essential data in the page and wrap slow async Server Components in <Suspense> with skeleton fallbacks so Next.js streams HTML progressively. Use loading.tsx for a route-level fallback. Start independent fetches in parallel to avoid waterfalls.
Solution
// app/products/[id]/page.tsx
import { Suspense } from "react";
export default async function ProductPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
const product = await getProduct(id); // fast, needed for the shell
const reviewsPromise = getReviews(id); // start early, don't await yet
return (
<main>
<ProductDetails product={product} />
<Suspense fallback={<ReviewsSkeleton />}>
<Reviews promise={reviewsPromise} />
</Suspense>
<Suspense fallback={<RecommendationsSkeleton />}>
<Recommendations productId={id} /> {/* slow service */}
</Suspense>
</main>
);
}
async function Reviews({ promise }: { promise: Promise<Review[]> }) {
const reviews = await promise;
return <ReviewList reviews={reviews} />;
}
async function Recommendations({ productId }: { productId: string }) {
const items = await getRecommendations(productId); // may take 1–2 s
return <ProductCarousel items={items} />;
}
Pitfalls
- Awaiting all data at the top of the page (no streaming).
- Sequential awaits that could run in parallel.
- Fallbacks that cause large layout shifts (size skeletons correctly).
Variations
loading.tsxper route segment for navigation-level loading UI.- Partial Prerendering / Cache Components to serve a static shell with dynamic holes.
Further reading: Next.js: Streaming
Reference: https://nextjs.org/docs/app/getting-started/fetching-data#streaming
More Next.js recipes
- Add a Content Security Policy with nonces in Next.js
- Add dark mode to Next.js without a flash
- Add SEO metadata, Open Graph and sitemaps
- Avoid data-fetching waterfalls in Server Components
- Build a validated JSON API with Route Handlers
- Create encrypted session cookies in Next.js
- Handle errors and 404s in the App Router
- Handle forms with Server Actions and validation