Caching Semantics in Next.js 15: Whatβs Changed? (Chapter 2)
π Introduction
Next.js 15 introduces a significant change in how caching works, moving towards an explicit opt-in model. Fetch requests, GET Route Handlers, and client navigations are no longer cached by default, ensuring more predictable and dynamic data fetching.
In this article, weβll dive deep into:
- What changed in caching behavior
- How to explicitly enable caching
- When and why to use different caching strategies
- Performance implications of this update
Let's break it down. π
β‘ What Changed in Next.js 15 Caching?
Previously, Next.js automatically cached fetch requests, API routes, and client-side navigations unless explicitly set to no-store
. This could lead to stale data issues, where users received outdated responses unexpectedly.
Now, in Next.js 15:
fetch
requests default tono-store
(previouslyforce-cache
).- GET Route Handlers are no longer cached automatically.
- Client-side navigations always fetch fresh data unless caching is manually configured.
This shift gives developers more control over caching behavior, reducing unexpected results. However, it also requires explicit configuration to optimize performance.
π§ How to Enable Caching Explicitly
Since caching is no longer automatic, developers must opt-in using force-cache
, next.revalidate
, or HTTP headers.
1. Enabling Fetch Caching
By default, fetch requests always retrieve fresh data unless explicitly cached.
β Example: Caching Fetch Requests
1async function getProducts() {2const res = await fetch("https://api.example.com/products", {3cache: "force-cache", // Opt into caching4});5return res.json();6}7
Alternatively, you can cache responses for a set period using next.revalidate
:
1async function getProducts() {2const res = await fetch("https://api.example.com/products", {3next: { revalidate: 60 }, // Cache response but refresh every 60 seconds4});5return res.json();6}7
2. Caching GET Route Handlers (app/api/route.ts
)
In earlier versions, GET API routes automatically cached responses. Now, to enable caching, you need to use explicit headers.
β Example: Caching a GET API Route
1import { NextResponse } from "next/server";23export async function GET() {4const data = await fetch("https://api.example.com/data", {5cache: "force-cache", // Opt into caching6});78return NextResponse.json(await data.json(), {9headers: {10"Cache-Control": "public, max-age=300", // Cache for 5 minutes11},12});13}14
3. Enabling Client-Side Page Caching
If a page fetches data dynamically and you want to cache responses, use next.revalidate
.
β Example: Opting Into Page Caching
1export async function getServerSideProps() {2const data = await fetch("https://api.example.com/data", {3next: { revalidate: 120 }, // Cache for 2 minutes4});56return {7props: { data: await data.json() },8};9}10
π Performance Implications
Since caching is opt-in, applications that rely on frequent API calls may experience increased request volume. Hereβs how this change affects performance:
π΄ Potential Drawbacks
- Higher API request volume since fresh data is always fetched unless explicitly cached.
- Slower client-side transitions due to missing automatic caching.
- Unexpected behavior in legacy applications that relied on implicit caching.
β When This Change is Beneficial
- Ensures data consistency by always fetching fresh content.
- Prevents stale data issues, especially in dynamic applications.
- Gives developers control over caching, reducing unexpected side effects.
π Best Practices
- Use
next.revalidate
for periodic caching instead of full persistence. - Cache only non-critical or rarely changing data.
- Apply Cache-Control headers in API responses where needed.
π Conclusion
Next.js 15βs explicit caching model improves data consistency but requires developers to opt into caching manually. While this may increase API load, it ensures predictable behavior across dynamic applications.
By using strategies like force-cache
, next.revalidate
, and explicit cache headers, you can optimize performance while maintaining fresh data.
For further insights, check out:
Would you like me to add a performance benchmark comparison for different caching strategies? π