--- title: Strategic Suspense Boundaries impact: HIGH impactDescription: faster initial paint tags: async, suspense, streaming, layout-shift --- ## Strategic Suspense Boundaries Instead of awaiting data in async components before returning JSX, use Suspense boundaries to show the wrapper UI faster while data loads. **Incorrect (wrapper blocked by data fetching):** ```tsx async function Page() { const data = await fetchData() // Blocks entire page return (
Sidebar
Header
Footer
) } ``` The entire layout waits for data even though only the middle section needs it. **Correct (wrapper shows immediately, data streams in):** ```tsx function Page() { return (
Sidebar
Header
}>
Footer
) } async function DataDisplay() { const data = await fetchData() // Only blocks this component return
{data.content}
} ``` Sidebar, Header, and Footer render immediately. Only DataDisplay waits for data. **Alternative (share promise across components):** ```tsx function Page() { // Start fetch immediately, but don't await const dataPromise = fetchData() return (
Sidebar
Header
}>
Footer
) } function DataDisplay({ dataPromise }: { dataPromise: Promise }) { const data = use(dataPromise) // Unwraps the promise return
{data.content}
} function DataSummary({ dataPromise }: { dataPromise: Promise }) { const data = use(dataPromise) // Reuses the same promise return
{data.summary}
} ``` Both components share the same promise, so only one fetch occurs. Layout renders immediately while both components wait together. **When NOT to use this pattern:** - Critical data needed for layout decisions (affects positioning) - SEO-critical content above the fold - Small, fast queries where suspense overhead isn't worth it - When you want to avoid layout shift (loading → content jump) **Trade-off:** Faster initial paint vs potential layout shift. Choose based on your UX priorities.