Dynamic IO API (v15)

Explicitly declaring dynamic boundaries.

Next.js3 min readConcept 66 of 66

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.

app/dashboard/page.tsx
export default async function Dashboard() {
// 1. Statically generated at build time
const header = <Header/>;
Build Time
await connection();
Compiler Halted
// 2. Execution resumes dynamically at runtime
const user = await db.fetchUser();
Request Time
return (
<>{header}{user}</>
);
}

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1What does calling `await connection()` do during the Next.js build process?

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.