
Next.js dynamicParams
generateStaticParams tells Next.js which specific values of a dynamic segment to prerender at build time. But real traffic doesn't always stick to your prerendered list — a new blog post gets published after your last build, a product ID gets requested that wasn't in your sample set. dynamicParams is the single boolean that decides what happens the moment a request arrives for a dynamic value you didn't prerender: generate it on the fly, or refuse and return a 404.
The Option
export const dynamicParams = true; // true | false
true(the default): Dynamic route segments not included ingenerateStaticParamsare generated at request time — the first visitor to hit an unlisted value triggers a fresh render, same as any dynamic route, and (depending on your caching setup) that result can then be cached for subsequent requests.false: Any dynamic route segment not included ingenerateStaticParamsreturns a 404 instead — no fallback rendering attempt, no on-demand generation. If it wasn't in your prerendered list, it doesn't exist as far as visitors are concerned.
When You'd Actually Choose false
The default (true) is right for the overwhelming majority of use cases — a blog where new posts should be immediately visible even before the next deploy, a product catalog where inventory changes between builds. But false earns its place in one specific, deliberate scenario: when your prerendered list is meant to be the complete, authoritative set of valid values, and anything outside it genuinely shouldn't exist as a real page.
Concretely: a documentation site with a fixed, curated list of page slugs, where visiting an unlisted slug should behave exactly like visiting any other genuinely nonexistent URL — a clean 404, not an attempt to render content for a value nobody intended to be reachable. Setting dynamicParams = false here is a deliberate security/correctness choice, not just a performance one: it prevents the segment from ever rendering for values you didn't explicitly enumerate, closing off a class of unexpected-input handling you'd otherwise need to guard against inside the page component itself.
Migrating From the Pages Router
If you're coming from getStaticPaths in the Pages Router, dynamicParams is the direct, if slightly restructured, successor to its fallback option — specifically replacing the three-way fallback: true | false | 'blocking' choice. The mapping is straightforward: fallback: false corresponds to dynamicParams = false; fallback: true or fallback: 'blocking' both correspond to dynamicParams = true (the App Router's request-time generation doesn't distinguish a client-visible loading state from a blocking wait the way fallback: true historically did in the Pages Router — that distinction is instead handled through loading.js and Suspense boundaries as part of the broader rendering model, not through this specific config option).
The One Restriction Worth Knowing Upfront
dynamicParams is not available when Cache Components is enabled. If your project has adopted the newer Cache Components model, this option simply isn't part of that model's configuration surface — it belongs to the previous, route-segment-config-driven caching approach. Under Cache Components, the equivalent behavior (what happens for unlisted dynamic values) is governed by how you structure generateStaticParams together with Suspense boundaries and the use cache directive, rather than by a single boolean flag. If you're migrating a project to Cache Components and it currently sets dynamicParams explicitly, that export needs to be removed as part of the migration — it won't cause an error by lingering, but it also won't do anything once Cache Components takes over that segment's rendering strategy.
Key Takeaways
| Value | Behavior |
|---|---|
true (default) | Unlisted dynamic values are generated at request time |
false | Unlisted dynamic values return a 404 — no on-demand generation attempted |
| Pages Router equivalent | Replaces getStaticPaths's fallback: true | false | 'blocking' option |
| Cache Components | This option is unavailable — the equivalent behavior is expressed differently under that model |
dynamicParams is a small option with an outsized effect on how your app handles the gap between "what I prerendered" and "what visitors actually request." Leave it at the default unless you have a specific, deliberate reason to treat your prerendered param list as a closed, authoritative set — and if you're on Cache Components, don't reach for it at all.


