Dynamic IO API (v15)
Explicitly declaring dynamic boundaries.
The Shift in Caching Defaults
In Next.js 14, every fetch() was aggressively cached by default. While fast, this led to widespread confusion when live databases updated but the website didn't.
The experimental **Dynamic IO** flag in Next.js 15 flips this paradigm. It defaults to treating IO (like database queries and headers) as dynamic, requiring you to explicitly opt-in to caching.
The Connection API
To give developers precise control over where a static build stops and dynamic execution begins, Next.js introduced the connection() API.
When the Next.js compiler hits await connection() during the build, it immediately stops statically rendering that branch of the React tree and leaves a Suspense boundary for dynamic execution.
Halting the Build
typescript
import { connection } from 'next/server';
export default async function Dashboard() {
// Everything above this line can be statically generated
// Halt static generation here. Wait for a real user request.
await connection();
// Everything below this line executes dynamically at runtime
const data = await fetchUserData();
return <Profile data={data} />;
}
The Static Halt
Watch how the Next.js compiler sweeps through the code but is physically stopped by the connection boundary.
const header = <Header/>;
const user = await db.fetchUser();
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- Dynamic IO is an experimental flag in Next.js 15 that changes caching defaults.
- It moves away from implicit aggressive caching to explicit granular caching.
await connection()is used to explicitly mark a dynamic IO boundary, halting static generation.
Done with this concept?
Mark it complete to track your progress. No login needed.