Control dynamic rendering in Next.js using the dynamic route segment config ('auto', 'force-dynamic', 'error', 'force-static'), dynamicParams, and granular fetch caching options, shifting from page-level decisions to component-level control [citation:2][citation:5].
Next.js provides multiple ways to control rendering behavior, ranging from coarse-grained route-level configuration to fine-grained per-fetch control. The primary mechanism is the dynamic route segment config exported from layout.tsx, page.tsx, or route.ts files, which allows you to override the default rendering strategy for that segment [citation:2][citation:4].
The dynamic configuration offers four distinct modes. 'auto' (the default) caches as much as possible while still allowing components to opt into dynamic behavior. 'force-dynamic' forces dynamic rendering for each request, equivalent to setting { cache: 'no-store' } on all fetches and is useful for user-specific dashboards or real-time data [citation:2][citation:9]. 'error' enforces static rendering and throws an error if any dynamic APIs are used, helping maintain static builds. 'force-static' also forces static rendering but makes dynamic APIs return empty values, useful for pages that should be static but are impacted by dynamic functions like cookies() [citation:2][citation:7].
For dynamic routes, the dynamicParams configuration controls what happens when a visitor requests a path not generated by generateStaticParams. When true (default), Next.js generates the page on-demand (streaming server rendering). When false, non-generated paths return a 404. This replaces the fallback option from the Pages Router [citation:2][citation:7].
Rather than forcing entire routes to be static or dynamic, Next.js recommends granular caching at the fetch request level. You can control individual data fetches using the cache and next.revalidate options, allowing static and dynamic content to coexist within the same page [citation:5].
Next.js automatically opts pages into dynamic rendering when they use dynamic functions like cookies(), headers(), or searchParams, or when they contain uncached fetches. This automatic detection allows you to rely on the default 'auto' setting while letting the framework make intelligent rendering decisions based on your code [citation:9][citation:10].
Use 'auto' as default: Let Next.js automatically determine the optimal rendering strategy based on your data fetching patterns.
Prefer granular fetch caching: Use cache: 'force-cache' for static data, cache: 'no-store' for dynamic data, and next.revalidate for ISR.
Use dynamic: 'force-dynamic' for user-specific pages: Dashboards, profile pages, and real-time data that change per request.
Use dynamic: 'error' to enforce static builds: Ensure pages remain static and fail the build if dynamic APIs are accidentally introduced.
Avoid overusing force-dynamic: The Next.js team recommends granular fetch caching over forcing entire routes to be dynamic, as it enables future optimizations like partial static subtrees [citation:1][citation:5].