
- Next.js - Home
- Next.js - Overview
- Next.js - Project Setup
- Next.js - Folder Structure
- Next.js - App Router
- Next.js - Page Router
- Next.js Features
- Next.js - Pages
- Next.js - Data Fetching
- Next.js - ISR
- Next.js - Static File Serving
- Next.js - Pre-Rendering
- Next.js - Partial Pre Rendering
- Next.js - Server Side Rendering
- Next.js - Client Side Rendering
- Next.js Routing
- Next.js - Routing
- Next.js - Nested Routing
- Next.js - Dynamic Routing
- Next.js - Parallel Routing
- Next.js - Imperative Routing
- Next.js - Shallow Routing
- Next.js - Intercepting Routes
- Next.js - Redirecting Routes
- Next.js - Navigation and Linking
- Next.js Configuration
- Next.js - TypeScript
- Next.js - Environment Variables
- Next.js - File Conventions
- Next.js - ESLint
- Next.js API & Backend
- Next.js - API Routes
- Next.js - Dynamic API Routes
- Next.js - Route Handlers
- Next.js - API MiddleWares
- Next.js - Response Helpers
- Next.js API Reference
- Next.js - CLI Commands
- Next.js - Functions
- Next.js - Directives
- Next.js - Components
- Next.js - Image Component
- Next.js - Font Component
- Next.js - Head Component
- Next.js - Form Component
- Next.js - Link Component
- Next.js - Script Component
- Next.js Styling & SEO
- Next.js - CSS Support
- Next.js - Global CSS Support
- Next.js - Meta Data
- Next.js Advanced Topics
- Next.js - Error Handling
- Next.js - Server Actions
- Next.js - Fast Refresh
- Next.js - Internationalization
- Next.js - Authentication
- Next.js - Session Management
- Next.js - Authorization
- Next.js - Caching
- Next.js - Data Caching
- Next.js - Router Caching
- Next.js - Full Route Caching
- Next.js - Request Memoization
- Next.js Performance Optimization
- Next.js - Optimizations
- Next.js - Image Optimization
- Next.js - Lazy Loading
- Next.js - Font Optimization
- Next.js - Video Optimization
- Next.js - Script Optimization
- Next.js - Memory Optimization
- Next.js - Using OpenTelemetry
- Next.js - Package Bundling Optimization
- Next.js Testing
- Next.js - Testing
- Next.js - Testing with Jest
- Next.js - Testing with Cypress
- Next.js - Testing with Vitest
- Next.js - Testing with Playwright
- Next.js Debugging & Deployment
- Next.js - Debugging
- Next.js - Deployment
- Next.js Useful Resources
- Next.js - Interview Questions
- Next.js - Quick Guide
- Next.js - Useful Resources
- Next.js - Discussion
Next.js - Full Route Caching
In this chapter, we will learn Full Route Caching in Next.js, how it works, and how to completely clear full route cache.
What is Full Route Caching?
Full Route Caching is Next.js's default caching behavior where it statically generates and caches entire routes at build time. This optimization technique allows to serve the cached route instead of rendering on the server for every request, resulting in faster page loads.
How it Works?
- When app is build for deployment, Next.js automatically caches the entire route segment, including the layout, page, and metadata.
- Each cached route is served as static HTML to users
- The cache persists across deployments unless invalidated in the code.
Invalidate Full Route Cache
Full Route Caching can be invalidated in two ways:
- Revalidating Data: Revalidating the Data Cache, will in turn invalidate the Router Cache by re-rendering components on the server and caching the new render output.
- Redeploying: Redeploying the App with a new build will clear all Routing caches. ( Only Data-Cache persists across deployment )
Clear Full Route Cache
Whether a route is cached or not at build time depends on whether it's statically or dynamically rendered. Static routes are cached by default, whereas dynamic routes are rendered at request time, and not cached. You can opt out of the Full Route Cache, or in other words, dynamically render components for every incoming request, by:
Using Force Dynamic
Force Dynamic is a technique used to opt out of Full Route Caching. It forces Next.js to render the page at request time, instead of serving the cached static HTML.
In the code snippet below, we have a dynamic page that displays a random data. We will display the random data with timestamp on the page.
// Set as force dynamic page export const dynamic = 'force-dynamic' async function getData() { // Simulating an API call with random data to demonstrate no caching const randomNumber = Math.floor(Math.random() * 100) return { timestamp: new Date().toISOString(), randomNumber } } export default async function Home() { const data = await getData() return ( <main> <h1>Force Dynamic Example</h1> <div> <p>Timestamp: {data.timestamp}</p> <p>Random Number: {data.randomNumber}</p> </div> </main> ) }
Output
The image below shows the output of the code snippet above. When we refresh the page, we are getting a different random number for each request. This is because the page is dynamically rendered at request time, and not cached.

Note: In development mode, you may not see the effect of force-dynamic, this is because Next.js automatically disables most caching to make development easier. To see caching effect, you have to build the app and start the production server.
Using Dynamic APIs
Dynamic APIs are server-side rendered APIs that are not cached at build time. The page containing dynamic APIs will be forcefully fetched from server. In the section below, we will setup a dynamic API that sets a cookie based on the theme selected by the user.
// Set up the cookie (Run in terminal) Invoke-WebRequest -Uri "http://localhost:3000/api/set-cookie" -Headers @{theme="dark"} -Method GET
In the code snippet below, we have a dynamic API that sets a cookie based on the theme selected by the user. when we access the page, with different search parameters, we'll see them reflected in the output. This route will always be dynamically rendered because it uses runtime request information, which means no static HTML generated at build time.
// app/api/set-cookie/route.ts import { cookies } from 'next/headers' import { NextResponse } from 'next/server' export async function GET(request: Request) { const theme = request.headers.get('theme') || 'light' // Wait for the cookieStore const cookieStore = await cookies() cookieStore.set('theme', theme) return NextResponse.json({ message: 'Cookie set successfully' }) } // app/dynamic-data/page.tsx import { cookies, headers } from 'next/headers' export default function DynamicPage({searchParams,}: { searchParams: { [key: string]: string | string[] | undefined }}) { const cookieStore = cookies() const headersList = headers() // Get specific cookie const theme = cookieStore.get('theme') // Get specific header const userAgent = headersList.get('user-agent') const referer = headersList.get('referer') return ( <div "p-4"> <h1>Dynamic Data Example</h1> <div"> {/* Display Search Parameters */} <section> <h2>Search Parameters:</h2> <pre> {JSON.stringify(searchParams, null, 2)} </pre> </section> {/* Display Cookies */} <section> <h2>Cookies:</h2> <div> <p>Theme Cookie: {theme?.value || 'Not set'}</p> <p>All Cookies:</p> <pre> {JSON.stringify(cookieStore.getAll(), null, 2)} </pre> </div> </section> </div> </div> ) }
Output
The image below shows the output of the code snippet above. The search parameters are displayed in the first section, and the cookies are displayed in the second section. For each request, a new page is rendered with the search parameters and cookies displayed.
