export const instant
Declares that navigations into a segment should render immediately, and validates that they do.
type InstantConfig =
| true
| false
| {
level?: 'warning'
}
export const instant: InstantConfig = true- Added in Next.js v16.3.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$trueoptional | boolean literal | Opts the segment into validation at whatever level is configured globally. With the framework defaults, validation runs in development only and surfaces errors in the dev overlay. |
$falseoptional | boolean literal | Opts the segment out of validation entirely, marking it as allowed to block when navigating to it. A false higher in the tree also disables static shell validation for the routes beneath it. |
${ level }optional | { level?: 'warning' } | Opts in with additional options. 'warning' validates in development only; errors appear in the dev overlay and the build is unaffected. It is the only level available today, so there is no need to specify it. |
Errors
Using instant in a Client Component throws an error. The export is only read when the cacheComponents flag is enabled.
Changelog
- PHP v16.3.0instant export introduced (Cache Components only), as part of the Instant Navigations release. The API reference lists this as v16.x.x.
- PHP v16.3.0The cache-components-instant-false codemod adds export const instant = false to every page, layout and default file that does not already export it, so cacheComponents can be enabled and the opt-outs removed route by route: npx @next/codemod@canary cache-components-instant-false ./app
instant is an assertion, not an optimisation. It tells Next.js what to expect from navigations through a segment, and Next.js then surfaces any code that would stop the UI from updating immediately. Nothing about the page gets faster on its own — you get an error in the dev overlay naming the component that blocks.
Reading the values
true validates the segment. false says this segment is allowed to block. The interesting case is the pair: a shared layout that cannot load instantly gets false, while the pages beneath it get true, so navigating into the section may block but moving between tabs is held to the instant standard.
What trips people up
- Validation happens at every shared layout boundary, on page loads and HMR updates. The usual fix for an error is to cache the offending data with
'use cache'or wrap it in<Suspense>. - Dev is not a fair test. Next.js does not prefetch in development, so navigations feel slower than they will under
next start; validation reflects production behaviour, not what you observe. falsewins upward. For the static-shell check, afalsehigher in the tree takes precedence over any deepertrue— putting it on the root layout silently disables shell validation for the entire app. Place it as low as possible.
Example
export const instant = true
export default async function TabPage({
params,
}: {
params: Promise<{ tab: string }>
}) {
const { tab } = await params
return (
<section>
<h1>{tab}</h1>
<TabContent tab={tab} />
</section>
)
}
async function TabContent({ tab }: { tab: string }) {
'use cache'
const res = await fetch(`https://api.example.com/tabs/${tab}`)
const data: { body: string } = await res.json()
return <p>{data.body}</p>
}When to use it
- Assert that switching between tabs under a shared layout never blocks on the network.
- Exempt a slow shared layout while still holding the pages beneath it to instant navigation.
- Opt an entire app out of Cache Components validation with the codemod, then re-enable it route by route.
Frequently asked questions
Why does export const instant throw an error in my component?
Because instant cannot be used in Client Components — move it to a Server Component page or layout, and make sure the cacheComponents flag is enabled, since the export is otherwise ignored.
How do I turn off Cache Components static shell validation for a route?
Make sure the highest instant config in that route's tree is false — a false higher in the tree takes precedence over any deeper true — and place it as low as possible so the rest of the app keeps validating.
Why do navigations still feel slow in development after setting instant = true?
Next.js does not perform prefetches in development, so navigations will not feel as instant as they do in production; validation reflects what happens under next start, where prefetching is enabled.
More examples
A blocking layout with instant pages beneath it
Navigations from outside into a tab are allowed to block at the layout, while navigations between tabs are validated for instant UI. This is the documented pattern for a shared layout that cannot load instantly but sits above pages that must.
// app/tabs/layout.tsx
export const instant = false
export default function TabsLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<div>
<nav>{/* tab links */}</nav>
{children}
</div>
)
}
// app/tabs/[tab]/page.tsx
export const instant = true
export default async function TabPage({
params,
}: {
params: Promise<{ tab: string }>
}) {
const { tab } = await params
return <h1>{tab}</h1>
}Fixing a validation error
Each validation error names the component that would block navigation. The two documented fixes are caching the data with 'use cache' or wrapping the component in a Suspense boundary, as here — the heading renders instantly and the items stream in.
// app/feed/page.tsx
import { Suspense } from 'react'
export const instant = true
export default function FeedPage() {
return (
<main>
<h1>Feed</h1>
{/* Without the boundary, validation reports that Items
blocks the navigation from updating immediately. */}
<Suspense fallback={<p>Loading items…</p>}>
<Items />
</Suspense>
</main>
)
}
async function Items() {
const res = await fetch('https://api.example.com/feed')
const items: { id: string; title: string }[] = await res.json()
return (
<ul>
{items.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
)
}Setting the validation level explicitly
'warning' is the only level available today, so the object form is equivalent to instant = true. The commented config shows the alternative lever: 'manual-warning' limits validation to segments that opt in explicitly, instead of implicitly validating every Page and Default segment.
// app/reports/page.tsx
export const instant = {
level: 'warning',
}
export default function ReportsPage() {
return <h1>Reports</h1>
}
// next.config.js — tuning the global default instead
// module.exports = {
// cacheComponents: true,
// experimental: {
// instantInsights: {
// validationLevel: 'manual-warning',
// },
// },
// }
Discussion