{"id":167,"date":"2026-10-05T04:44:46","date_gmt":"2026-10-05T04:44:46","guid":{"rendered":"https:\/\/devdojo.co.in\/?p=167"},"modified":"2026-10-05T04:44:46","modified_gmt":"2026-10-05T04:44:46","slug":"nextjs-use-cache","status":"publish","type":"post","link":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/","title":{"rendered":"Next.js use cache Explained: Cache Components, cacheLife &#038; cacheTag (2026 Guide)"},"content":{"rendered":"\n<div class=\"dd-post\">\n<style>\n.single article:has(.dd-hero) .entry-media{display:none}\n.dd-post{--dd-accent:#3178c6;--dd-accent2:#7c5cff;--dd-ink:#0b1020;--dd-soft:#f3f5fb;--dd-line:#dfe3f0;line-height:1.7}\n.dd-post .dd-hero{border-radius:16px;overflow:hidden;margin:0 0 1.5em;box-shadow:0 10px 30px rgba(11,16,32,.25)}\n.dd-post .dd-hero svg{display:block;width:100%;height:auto}\n.dd-post .ddb-node{transition:transform .25s ease,filter .25s ease;transform-box:fill-box;transform-origin:center;cursor:help}\n.dd-post .ddb-node:hover{transform:scale(1.05);filter:drop-shadow(0 0 12px rgba(124,92,255,.75))}\n.dd-post figure.dd-fig{margin:1.8em 0;text-align:center}\n.dd-post figure.dd-fig svg{width:100%;height:auto;border-radius:14px;background:#0f1430}\n.dd-post figure.dd-fig figcaption{font-size:.9em;color:#6b7280;margin-top:.5em}\n.dd-post .dd-tldr{background:linear-gradient(135deg,#eef4ff,#f4efff);border-left:5px solid var(--dd-accent2);padding:1em 1.2em;border-radius:10px;margin:1.5em 0;color:#1f2544}\n.dd-post .dd-tldr ul{margin:.4em 0 0 1.1em}\n.dd-post .dd-toc{background:var(--dd-soft);border:1px solid var(--dd-line);border-radius:12px;padding:1em 1.3em;margin:1.5em 0}\n.dd-post .dd-toc strong{display:block;margin-bottom:.4em;color:var(--dd-ink)}\n.dd-post .dd-toc ol{margin:0 0 0 1.2em;columns:2 260px;column-gap:2em}\n.dd-post .dd-toc a{text-decoration:none;color:var(--dd-accent)}\n.dd-post .dd-toc a:hover{text-decoration:underline}\n.dd-post .dd-note{background:#fff8e6;border-left:5px solid #f4b400;padding:.8em 1em;border-radius:8px;margin:1.2em 0;color:#3d3200}\n.dd-post .dd-tip{background:#e9fbf3;border-left:5px solid #12b886;padding:.8em 1em;border-radius:8px;margin:1.2em 0;color:#0b3d2c}\n.dd-post pre{background:#0f1430;color:#e6e9ff;padding:1.1em 1.2em;border-radius:12px;overflow-x:auto;font-size:.88em;line-height:1.55;margin:1em 0 1.4em}\n.dd-post pre,.dd-post pre code{white-space:pre!important;word-wrap:normal!important;overflow-wrap:normal!important}\n.dd-post pre code{display:block;background:none;color:inherit;padding:0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.92em}\n.dd-post .dd-file{display:inline-block;background:#1b2250;color:#a9b8ff;font:600 .78em ui-monospace,Menlo,monospace;padding:.25em .7em;border-radius:8px 8px 0 0;margin:1em 0 -1em}\n.dd-post :not(pre)>code{background:#eef1fa;color:#3b2bb3;padding:.1em .35em;border-radius:5px;font-size:.9em}\n.dd-post table{width:100%;border-collapse:collapse;margin:1em 0 1.5em;font-size:.95em;display:block;overflow-x:auto}\n.dd-post th,.dd-post td{border:1px solid var(--dd-line);padding:.6em .8em;text-align:left;vertical-align:top}\n.dd-post th{background:var(--dd-soft)}\n.dd-post .dd-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;margin:1.4em 0}\n.dd-post .dd-card{border-radius:14px;padding:1.1em;color:#fff;box-shadow:0 6px 18px rgba(11,16,32,.15);transition:transform .2s}\n.dd-post .dd-card:hover{transform:translateY(-4px)}\n.dd-post .dd-card h4{margin:.3em 0 .4em;color:#fff;font-size:1.1em}\n.dd-post .dd-card p{margin:0;font-size:.92em;opacity:.95}\n.dd-post .dd-card small{display:block;margin-top:.6em;opacity:.85;font-family:ui-monospace,Menlo,monospace}\n.dd-post .dd-c1{background:linear-gradient(135deg,#3178c6,#4cc9f0)}\n.dd-post .dd-c2{background:linear-gradient(135deg,#12b886,#80c9a0)}\n.dd-post .dd-c3{background:linear-gradient(135deg,#7c5cff,#c77dff)}\n.dd-post .dd-c4{background:linear-gradient(135deg,#f76707,#ffa94d)}\n\/* CSS-only tabs *\/\n.dd-post .dd-tabs-box{border:1px solid var(--dd-line);border-radius:14px;overflow:hidden;margin:1.5em 0;background:#fff;position:relative}\n.dd-post .dd-tabs-box > input{position:absolute;opacity:0;pointer-events:none}\n.dd-post .dd-tabbar{display:flex;flex-wrap:wrap;background:var(--dd-soft);border-bottom:1px solid var(--dd-line)}\n.dd-post .dd-tabbar label{flex:1 1 130px;padding:.75em .6em;text-align:center;cursor:pointer;font-weight:600;font-size:.92em;color:#47507a;border-bottom:3px solid transparent;transition:all .2s}\n.dd-post .dd-tabbar label:hover{background:#e8ecf8;color:var(--dd-ink)}\n.dd-post .dd-panel{display:none;padding:1.1em 1.3em}\n.dd-post .dd-panel h4{margin:.2em 0 .5em}\n.dd-post #ddt1:checked ~ .dd-tabbar label[for=ddt1],.dd-post #ddt2:checked ~ .dd-tabbar label[for=ddt2],.dd-post #ddt3:checked ~ .dd-tabbar label[for=ddt3],.dd-post #ddt4:checked ~ .dd-tabbar label[for=ddt4]{color:var(--dd-accent2);border-bottom-color:var(--dd-accent2);background:#fff}\n.dd-post #ddt1:checked ~ .dd-p1,.dd-post #ddt2:checked ~ .dd-p2,.dd-post #ddt3:checked ~ .dd-p3,.dd-post #ddt4:checked ~ .dd-p4{display:block}\n.dd-post #ddt1:focus-visible ~ .dd-tabbar label[for=ddt1],.dd-post #ddt2:focus-visible ~ .dd-tabbar label[for=ddt2],.dd-post #ddt3:focus-visible ~ .dd-tabbar label[for=ddt3],.dd-post #ddt4:focus-visible ~ .dd-tabbar label[for=ddt4]{outline:2px solid var(--dd-accent2);outline-offset:-2px}\n.dd-post details.dd-faq{border:1px solid var(--dd-line);border-radius:10px;padding:.7em 1em;margin:.6em 0;background:#fff}\n.dd-post details.dd-faq summary{cursor:pointer;font-weight:600;color:var(--dd-ink)}\n.dd-post details.dd-faq[open]{background:var(--dd-soft)}\n.dd-post details.dd-faq p{margin:.6em 0 .2em}\n.dd-post .dd-cta{background:linear-gradient(135deg,#0b1020,#151b3b);color:#e6e9ff;border-radius:16px;padding:1.5em 1.6em;margin:2em 0 1em;text-align:center;box-shadow:0 10px 30px rgba(11,16,32,.25)}\n.dd-post .dd-cta h3{color:#fff;margin:.1em 0 .4em}\n.dd-post .dd-cta p{margin:.3em 0;color:#c7cbe0}\n.dd-post .dd-cta a{display:inline-block;margin-top:.7em;background:linear-gradient(135deg,#3178c6,#7c5cff);color:#fff!important;padding:.6em 1.3em;border-radius:999px;text-decoration:none;font-weight:700}\n.dd-post ul.dd-check{list-style:none;margin-left:0;padding-left:0}\n.dd-post ul.dd-check li{padding-left:1.7em;position:relative;margin:.35em 0}\n.dd-post ul.dd-check li:before{content:\"\u2713\";position:absolute;left:0;top:0;color:#12b886;font-weight:800}\n<\/style>\n\n<div class=\"dd-hero\" role=\"img\" aria-label=\"Next.js use cache explained: Cache Components, cacheLife and cacheTag\">\n<svg viewBox=\"0 0 1200 520\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" font-family=\"Inter, Segoe UI, Arial, sans-serif\">\n<defs>\n<linearGradient id=\"hbg\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"><stop offset=\"0\" stop-color=\"#0b1020\"\/><stop offset=\"1\" stop-color=\"#151b3b\"\/><\/linearGradient>\n<linearGradient id=\"hacc\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\"><stop offset=\"0\" stop-color=\"#3178c6\"\/><stop offset=\"1\" stop-color=\"#7c5cff\"\/><\/linearGradient>\n<radialGradient id=\"hglow\" cx=\".8\" cy=\".2\" r=\".6\"><stop offset=\"0\" stop-color=\"#7c5cff\" stop-opacity=\".35\"\/><stop offset=\"1\" stop-color=\"#7c5cff\" stop-opacity=\"0\"\/><\/radialGradient>\n<\/defs>\n<rect class=\"dd-bg\" x=\"0\" y=\"0\" width=\"1200\" height=\"520\" fill=\"url(#hbg)\"\/>\n<rect class=\"dd-bg\" x=\"0\" y=\"0\" width=\"1200\" height=\"520\" fill=\"url(#hglow)\"\/>\n<g stroke=\"#ffffff\" stroke-opacity=\".05\">\n<path d=\"M0 104H1200M0 208H1200M0 312H1200M0 416H1200M150 0V520M300 0V520M450 0V520M600 0V520M750 0V520M900 0V520M1050 0V520\"\/>\n<\/g>\n<text x=\"70\" y=\"92\" fill=\"#a9b8ff\" font-size=\"22\" font-weight=\"700\" letter-spacing=\"4\">DEVDOJO \u00b7 NEXT.JS 16.3<\/text>\n<text x=\"70\" y=\"160\" fill=\"#ffffff\" font-size=\"58\" font-weight=\"800\">Next.js &#8220;use cache&#8221;<\/text>\n<text x=\"70\" y=\"226\" fill=\"url(#hacc)\" font-size=\"46\" font-weight=\"800\">Explained, Step by Step<\/text>\n<text x=\"70\" y=\"276\" fill=\"#c7cbe0\" font-size=\"24\">Cache Components \u00b7 cacheLife \u00b7 cacheTag \u00b7 updateTag<\/text>\n<rect x=\"70\" y=\"306\" width=\"250\" height=\"44\" rx=\"22\" fill=\"url(#hacc)\"\/>\n<text x=\"195\" y=\"335\" fill=\"#fff\" font-size=\"19\" font-weight=\"700\" text-anchor=\"middle\">Beginner friendly<\/text>\n<path id=\"hp1\" d=\"M760 140 C 860 140, 860 260, 960 260\" fill=\"none\" stroke=\"#3178c6\" stroke-width=\"3\" stroke-dasharray=\"6 8\" opacity=\".8\"\/>\n<path id=\"hp2\" d=\"M760 380 C 860 380, 860 260, 960 260\" fill=\"none\" stroke=\"#7c5cff\" stroke-width=\"3\" stroke-dasharray=\"6 8\" opacity=\".8\"\/>\n<path id=\"hp3\" d=\"M1040 300 C 1040 380, 1040 400, 1040 430\" fill=\"none\" stroke=\"#4cc9f0\" stroke-width=\"3\" stroke-dasharray=\"6 8\" opacity=\".8\"\/>\n<circle r=\"7\" fill=\"#4cc9f0\"><animateMotion dur=\"2.6s\" repeatCount=\"indefinite\"><mpath href=\"#hp1\"\/><\/animateMotion><\/circle>\n<circle r=\"7\" fill=\"#c77dff\"><animateMotion dur=\"3.1s\" repeatCount=\"indefinite\" begin=\"0.6s\"><mpath href=\"#hp2\"\/><\/animateMotion><\/circle>\n<circle r=\"6\" fill=\"#7ee787\"><animateMotion dur=\"1.8s\" repeatCount=\"indefinite\"><mpath href=\"#hp3\"\/><\/animateMotion><\/circle>\n<g class=\"ddb-node\"><title>Static parts: prerendered at build time<\/title>\n<rect x=\"640\" y=\"104\" width=\"140\" height=\"72\" rx=\"14\" fill=\"#1a2150\" stroke=\"#3178c6\" stroke-width=\"2\"\/>\n<text x=\"710\" y=\"137\" fill=\"#fff\" font-size=\"18\" font-weight=\"700\" text-anchor=\"middle\">Static<\/text>\n<text x=\"710\" y=\"160\" fill=\"#a9b8ff\" font-size=\"14\" text-anchor=\"middle\">build time<\/text><\/g>\n<g class=\"ddb-node\"><title>Dynamic parts: streamed inside Suspense<\/title>\n<rect x=\"640\" y=\"344\" width=\"140\" height=\"72\" rx=\"14\" fill=\"#1a2150\" stroke=\"#7c5cff\" stroke-width=\"2\"\/>\n<text x=\"710\" y=\"377\" fill=\"#fff\" font-size=\"18\" font-weight=\"700\" text-anchor=\"middle\">Dynamic<\/text>\n<text x=\"710\" y=\"400\" fill=\"#c9b8ff\" font-size=\"14\" text-anchor=\"middle\">&lt;Suspense&gt;<\/text><\/g>\n<g class=\"ddb-node\"><title>&#8216;use cache&#8217;: cached result joins the static shell<\/title>\n<rect x=\"940\" y=\"220\" width=\"200\" height=\"80\" rx=\"16\" fill=\"url(#hacc)\"\/>\n<text x=\"1040\" y=\"255\" fill=\"#fff\" font-size=\"20\" font-weight=\"800\" text-anchor=\"middle\">&#8220;use cache&#8221;<\/text>\n<text x=\"1040\" y=\"281\" fill=\"#eef\" font-size=\"14\" text-anchor=\"middle\">cacheLife + cacheTag<\/text><\/g>\n<g class=\"ddb-node\"><title>Result: instant page with fresh data where needed<\/title>\n<rect x=\"960\" y=\"430\" width=\"160\" height=\"56\" rx=\"14\" fill=\"#12b886\"\/>\n<text x=\"1040\" y=\"465\" fill=\"#fff\" font-size=\"17\" font-weight=\"700\" text-anchor=\"middle\">Instant page<\/text><\/g>\n<\/svg>\n<\/div>\n\n<p>Caching in Next.js used to feel like magic you could not control: some <code>fetch<\/code> calls were cached, some were not, and nobody on the team was quite sure why. The <strong>Next.js use cache<\/strong> directive fixes that. Since Next.js 16, you turn on <em>Cache Components<\/em>, write <code>'use cache'<\/code> at the top of a function or component, and you decide exactly what is cached, for how long, and how to refresh it. In this guide you will learn the whole model step by step, with runnable code for Next.js 16.3 (the current Active LTS line).<\/p>\n\n<div class=\"dd-tldr\"><strong>TL;DR<\/strong>\n<ul>\n<li>Enable it with <code>cacheComponents: true<\/code> in <code>next.config.ts<\/code>. Without it, Next.js 16 is <em>dynamic by default<\/em>.<\/li>\n<li>Add <code>'use cache'<\/code> to an async function (data-level) or component (UI-level). Arguments become part of the cache key.<\/li>\n<li>Always pair it with <code>cacheLife('hours' | 'days' | ...)<\/code> and tag it with <code>cacheTag('posts')<\/code>.<\/li>\n<li>After a mutation: <code>updateTag()<\/code> in Server Actions (user sees change now) or <code>revalidateTag(tag, 'max')<\/code> for background refresh.<\/li>\n<li>Anything that reads <code>cookies()<\/code>, <code>headers()<\/code> or fresh data goes inside <code>&lt;Suspense&gt;<\/code>, not inside <code>'use cache'<\/code>.<\/li>\n<\/ul><\/div>\n\n<nav class=\"dd-toc\" aria-label=\"Table of contents\"><strong>Table of contents<\/strong>\n<ol>\n<li><a href=\"#what-is-use-cache\">What is the Next.js use cache directive?<\/a><\/li>\n<li><a href=\"#mental-model\">The mental model: static shell + holes<\/a><\/li>\n<li><a href=\"#enable\">Step 1: Enable Cache Components<\/a><\/li>\n<li><a href=\"#data-level\">Step 2: Data-level caching<\/a><\/li>\n<li><a href=\"#ui-level\">Step 3: UI-level caching with Suspense<\/a><\/li>\n<li><a href=\"#cachelife\">Step 4: Control freshness with cacheLife<\/a><\/li>\n<li><a href=\"#cachetag\">Step 5: cacheTag, updateTag and revalidateTag<\/a><\/li>\n<li><a href=\"#runtime\">Step 6: Cookies, headers and per-user data<\/a><\/li>\n<li><a href=\"#which-tool\">Interactive: which tool should I use?<\/a><\/li>\n<li><a href=\"#errors\">Common errors and fixes<\/a><\/li>\n<li><a href=\"#best-practices\">Best practices<\/a><\/li>\n<li><a href=\"#faq\">FAQ<\/a><\/li>\n<\/ol><\/nav>\n<\/div>\n\n\n\n<div class=\"dd-post\">\n<h2 id=\"what-is-use-cache\">What is the Next.js use cache directive?<\/h2>\n<p><code>'use cache'<\/code> is a directive, just like <code>'use client'<\/code> or <code>'use server'<\/code>. You place it as the first line inside an async function, an async Server Component, or at the top of a file. Next.js then stores the <strong>return value<\/strong> of that function and reuses it for later calls with the same inputs.<\/p>\n<p>It was introduced as the main caching primitive in Next.js 16.0 (October 2025) and, in 16.3, it also powers client-side caching, Partial Prefetching and &#8220;Instant Navigations&#8221;. The big idea is simple: <strong>nothing is cached unless you say so<\/strong>. That is the opposite of the old App Router behaviour in Next.js 13\u201314, where <code>fetch<\/code> was cached implicitly.<\/p>\n\n<div class=\"dd-cards\">\n<div class=\"dd-card dd-c1\"><h4>Explicit<\/h4><p>Only functions marked with <code>'use cache'<\/code> are cached. No hidden magic.<\/p><small>&#8216;use cache&#8217;<\/small><\/div>\n<div class=\"dd-card dd-c2\"><h4>Composable<\/h4><p>Cache a single DB query, a component, or an entire page.<\/p><small>data \u00b7 UI \u00b7 page<\/small><\/div>\n<div class=\"dd-card dd-c3\"><h4>Controllable<\/h4><p>Set lifetimes with profiles and invalidate precisely with tags.<\/p><small>cacheLife \u00b7 cacheTag<\/small><\/div>\n<div class=\"dd-card dd-c4\"><h4>Fast by design<\/h4><p>Cached output joins the prerendered static shell, served from a CDN.<\/p><small>Partial Prerendering<\/small><\/div>\n<\/div>\n\n<div class=\"dd-note\"><strong>Note:<\/strong> <code>'use cache'<\/code> works only in the App Router and only when Cache Components is enabled. If you are still on the Pages Router, nothing in this article applies to <code>pages\/<\/code>.<\/div>\n\n<h2 id=\"mental-model\">The mental model: a static shell with dynamic holes<\/h2>\n<p>With Cache Components, Next.js renders each route at build time and sorts every piece of UI into one of three buckets:<\/p>\n<ol>\n<li><strong>Static<\/strong> \u2013 pure code, module imports, synchronous reads. Prerendered automatically.<\/li>\n<li><strong>Cached<\/strong> \u2013 anything inside <code>'use cache'<\/code>. The result is prerendered too and becomes part of the <em>static shell<\/em>.<\/li>\n<li><strong>Dynamic<\/strong> \u2013 uncached fetches, <code>cookies()<\/code>, <code>headers()<\/code>, <code>searchParams<\/code>. These must sit inside <code>&lt;Suspense&gt;<\/code>. The fallback ships in the shell; the real content streams in at request time.<\/li>\n<\/ol>\n<p>This approach is called <strong>Partial Prerendering (PPR)<\/strong>, and it is the default behaviour once Cache Components is on. The diagram below shows how one product page is split.<\/p>\n\n<figure class=\"dd-fig\">\n<svg viewBox=\"0 0 900 430\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" font-family=\"Inter, Segoe UI, Arial, sans-serif\" role=\"img\" aria-label=\"Diagram of a page split into a static shell, cached blocks and dynamic Suspense holes\">\n<rect x=\"0\" y=\"0\" width=\"900\" height=\"430\" fill=\"#0f1430\"\/>\n<text x=\"30\" y=\"40\" fill=\"#a9b8ff\" font-size=\"16\" font-weight=\"700\" letter-spacing=\"2\">ONE ROUTE = STATIC SHELL + HOLES<\/text>\n<rect x=\"30\" y=\"60\" width=\"520\" height=\"345\" rx=\"14\" fill=\"#151b3b\" stroke=\"#2c3570\"\/>\n<rect x=\"50\" y=\"78\" width=\"480\" height=\"46\" rx=\"8\" fill=\"#3178c6\"\/>\n<text x=\"290\" y=\"107\" fill=\"#fff\" font-size=\"16\" font-weight=\"700\" text-anchor=\"middle\">Header + Nav (static)<\/text>\n<rect x=\"50\" y=\"138\" width=\"290\" height=\"150\" rx=\"8\" fill=\"#7c5cff\"\/>\n<text x=\"195\" y=\"200\" fill=\"#fff\" font-size=\"16\" font-weight=\"700\" text-anchor=\"middle\">Product details<\/text>\n<text x=\"195\" y=\"224\" fill=\"#efeaff\" font-size=\"14\" text-anchor=\"middle\">&#8216;use cache&#8217; \u00b7 cacheLife(&#8216;hours&#8217;)<\/text>\n<rect x=\"355\" y=\"138\" width=\"175\" height=\"150\" rx=\"8\" fill=\"none\" stroke=\"#4cc9f0\" stroke-width=\"2\" stroke-dasharray=\"7 6\"\/>\n<text x=\"442\" y=\"200\" fill=\"#4cc9f0\" font-size=\"16\" font-weight=\"700\" text-anchor=\"middle\">Cart<\/text>\n<text x=\"442\" y=\"224\" fill=\"#9fdcf0\" font-size=\"13\" text-anchor=\"middle\">cookies() \u2192 Suspense<\/text>\n<rect x=\"50\" y=\"302\" width=\"480\" height=\"86\" rx=\"8\" fill=\"none\" stroke=\"#4cc9f0\" stroke-width=\"2\" stroke-dasharray=\"7 6\"\/>\n<text x=\"290\" y=\"340\" fill=\"#4cc9f0\" font-size=\"16\" font-weight=\"700\" text-anchor=\"middle\">Live stock \/ reviews<\/text>\n<text x=\"290\" y=\"364\" fill=\"#9fdcf0\" font-size=\"13\" text-anchor=\"middle\">uncached fetch \u2192 streams at request time<\/text>\n<rect x=\"590\" y=\"90\" width=\"22\" height=\"22\" rx=\"5\" fill=\"#3178c6\"\/><text x=\"624\" y=\"107\" fill=\"#e6e9ff\" font-size=\"15\">Static: prerendered at build<\/text>\n<rect x=\"590\" y=\"135\" width=\"22\" height=\"22\" rx=\"5\" fill=\"#7c5cff\"\/><text x=\"624\" y=\"152\" fill=\"#e6e9ff\" font-size=\"15\">Cached: in the static shell<\/text>\n<rect x=\"590\" y=\"180\" width=\"22\" height=\"22\" rx=\"5\" fill=\"none\" stroke=\"#4cc9f0\" stroke-width=\"2\" stroke-dasharray=\"4 3\"\/><text x=\"624\" y=\"197\" fill=\"#e6e9ff\" font-size=\"15\">Dynamic hole: Suspense fallback<\/text>\n<text x=\"590\" y=\"260\" fill=\"#a9b8ff\" font-size=\"14\">CDN sends the shell instantly,<\/text>\n<text x=\"590\" y=\"282\" fill=\"#a9b8ff\" font-size=\"14\">then the server streams the<\/text>\n<text x=\"590\" y=\"304\" fill=\"#a9b8ff\" font-size=\"14\">dashed parts into place.<\/text>\n<circle r=\"6\" fill=\"#7ee787\"><animateMotion dur=\"3s\" repeatCount=\"indefinite\" path=\"M600 340 H 860\"\/><\/circle>\n<line x1=\"600\" y1=\"340\" x2=\"860\" y2=\"340\" stroke=\"#7ee787\" stroke-width=\"2\" stroke-dasharray=\"5 6\" opacity=\".6\"\/>\n<text x=\"730\" y=\"370\" fill=\"#7ee787\" font-size=\"13\" text-anchor=\"middle\">streaming\u2026<\/text>\n<\/svg>\n<figcaption>Figure 1: With Cache Components, static and cached parts form the shell; dynamic parts stream into Suspense holes.<\/figcaption>\n<\/figure>\n\n<h2 id=\"enable\">Step 1: Enable Cache Components<\/h2>\n<p>Create a new app (or upgrade an existing one) to the latest Next.js 16 release:<\/p>\n<pre><code># new project\nnpx create-next-app@latest my-cache-app\ncd my-cache-app\n\n# or upgrade an existing app\nnpm install next@latest react@latest react-dom@latest<\/code><\/pre>\n<p>Then switch the feature on in your config file:<\/p>\n<span class=\"dd-file\">next.config.ts<\/span>\n<pre><code>import type { NextConfig } from 'next'\n\nconst nextConfig: NextConfig = {\n  cacheComponents: true,\n}\n\nexport default nextConfig<\/code><\/pre>\n<div class=\"dd-tip\"><strong>Tip:<\/strong> In 16.3 you can also add <code>partialPrefetching: true<\/code> next to it to try Instant Navigations. Start with <code>cacheComponents<\/code> alone, get your routes clean, then add prefetching.<\/div>\n<p>Once enabled, old route segment options such as <code>export const dynamic = 'force-static'<\/code>, <code>export const revalidate = 60<\/code> and <code>fetchCache<\/code> are no longer used. Remove them and express the same intent with <code>'use cache'<\/code> and <code>cacheLife<\/code>. Next.js will tell you in the terminal if any are left.<\/p>\n\n<h2 id=\"data-level\">Step 2: Data-level caching<\/h2>\n<p>The easiest place to start is a data function. Here we cache a list of products coming from a database (or any API):<\/p>\n<span class=\"dd-file\">app\/lib\/data.ts<\/span>\n<pre><code>import { cacheLife, cacheTag } from 'next\/cache'\nimport { db } from '.\/db'\n\nexport async function getProducts() {\n  'use cache'\n  cacheLife('hours')      \/\/ fresh for about an hour\n  cacheTag('products')    \/\/ label so we can invalidate later\n\n  return db.product.findMany({ orderBy: { createdAt: 'desc' } })\n}\n\nexport async function getProduct(id: string) {\n  'use cache'\n  cacheLife('hours')\n  cacheTag('products', `product-${id}`)\n\n  return db.product.findUnique({ where: { id } })\n}<\/code><\/pre>\n<p>Notice <code>getProduct(id)<\/code>: the <code>id<\/code> argument is automatically part of the <strong>cache key<\/strong>. <code>getProduct('1')<\/code> and <code>getProduct('2')<\/code> get separate entries. Values captured from the surrounding scope are included in the key too.<\/p>\n<div class=\"dd-note\"><strong>Rule:<\/strong> arguments and return values must be serializable (strings, numbers, plain objects, arrays, Dates, etc.). You cannot pass class instances or functions as arguments and expect them to be part of the key.<\/div>\n\n<h2 id=\"ui-level\">Step 3: UI-level caching with Suspense<\/h2>\n<p>You can also cache a whole component. Below is a complete page that mixes all three buckets: static header, a cached post list, and a per-user block that reads cookies.<\/p>\n<span class=\"dd-file\">app\/blog\/page.tsx<\/span>\n<pre><code>import { Suspense } from 'react'\nimport { cookies } from 'next\/headers'\nimport { cacheLife, cacheTag } from 'next\/cache'\n\nexport default function BlogPage() {\n  return (\n    &lt;&gt;\n      {\/* 1. Static: prerendered automatically *\/}\n      &lt;header&gt;\n        &lt;h1&gt;DevDojo Blog&lt;\/h1&gt;\n      &lt;\/header&gt;\n\n      {\/* 2. Cached: becomes part of the static shell *\/}\n      &lt;PostList \/&gt;\n\n      {\/* 3. Dynamic: fallback in shell, content streams per request *\/}\n      &lt;Suspense fallback={&lt;p&gt;Loading your preferences\u2026&lt;\/p&gt;}&gt;\n        &lt;UserPreferences \/&gt;\n      &lt;\/Suspense&gt;\n    &lt;\/&gt;\n  )\n}\n\ntype Post = { id: number; title: string }\n\nasync function PostList() {\n  'use cache'\n  cacheLife('days')\n  cacheTag('posts')\n\n  const res = await fetch('https:\/\/jsonplaceholder.typicode.com\/posts?_limit=5')\n  const posts: Post[] = await res.json()\n\n  return (\n    &lt;ul&gt;\n      {posts.map((post) =&gt; (\n        &lt;li key={post.id}&gt;{post.title}&lt;\/li&gt;\n      ))}\n    &lt;\/ul&gt;\n  )\n}\n\nasync function UserPreferences() {\n  const theme = (await cookies()).get('theme')?.value ?? 'light'\n  return &lt;aside&gt;Your theme: {theme}&lt;\/aside&gt;\n}<\/code><\/pre>\n<p>Run <code>npm run build<\/code> and you will see this route marked as partially prerendered. The header and post list are in the HTML immediately; only <code>&lt;UserPreferences \/&gt;<\/code> waits for the request.<\/p>\n<div class=\"dd-tip\"><strong>Why does reading cookies not make the whole page dynamic?<\/strong> In the old model, one <code>cookies()<\/code> call opted the entire route into dynamic rendering. Now the <code>&lt;Suspense&gt;<\/code> boundary contains it, so the rest of the page stays static.<\/div>\n<\/div>\n\n\n\n<div class=\"dd-post\">\n<h2 id=\"cachelife\">Step 4: Control freshness with cacheLife<\/h2>\n<p><code>cacheLife()<\/code> tells Next.js how long a cached result stays good. Each profile has three timings:<\/p>\n<ul>\n<li><strong>stale<\/strong> \u2013 how long the browser can reuse the data without asking the server.<\/li>\n<li><strong>revalidate<\/strong> \u2013 after this, the next request gets the cached copy <em>and<\/em> triggers a background refresh (stale-while-revalidate).<\/li>\n<li><strong>expire<\/strong> \u2013 after this with no traffic, the next request waits for fresh data.<\/li>\n<\/ul>\n<p>These are the built-in profiles in Next.js 16.3:<\/p>\n<table>\n<thead><tr><th>Profile<\/th><th>Good for<\/th><th>stale<\/th><th>revalidate<\/th><th>expire<\/th><\/tr><\/thead>\n<tbody>\n<tr><td><code>default<\/code><\/td><td>Used when you don&#8217;t call cacheLife<\/td><td>5 min<\/td><td>15 min<\/td><td>never<\/td><\/tr>\n<tr><td><code>seconds<\/code><\/td><td>Live scores, prices<\/td><td>30 s<\/td><td>1 s<\/td><td>1 min<\/td><\/tr>\n<tr><td><code>minutes<\/code><\/td><td>Social feeds, news<\/td><td>5 min<\/td><td>1 min<\/td><td>1 hour<\/td><\/tr>\n<tr><td><code>hours<\/code><\/td><td>Inventory, weather<\/td><td>5 min<\/td><td>1 hour<\/td><td>1 day<\/td><\/tr>\n<tr><td><code>days<\/code><\/td><td>Blog posts, articles<\/td><td>5 min<\/td><td>1 day<\/td><td>1 week<\/td><\/tr>\n<tr><td><code>weeks<\/code><\/td><td>Podcasts, newsletters<\/td><td>5 min<\/td><td>1 week<\/td><td>30 days<\/td><\/tr>\n<tr><td><code>max<\/code><\/td><td>Legal pages, CMS content + webhook<\/td><td>5 min<\/td><td>30 days<\/td><td>1 year<\/td><\/tr>\n<\/tbody><\/table>\n<p>You can also define your own named profiles in the config, or pass an inline object for a one-off case:<\/p>\n<span class=\"dd-file\">next.config.ts<\/span>\n<pre><code>import type { NextConfig } from 'next'\n\nconst nextConfig: NextConfig = {\n  cacheComponents: true,\n  cacheLife: {\n    editorial: {\n      stale: 600,      \/\/ 10 minutes\n      revalidate: 3600, \/\/ 1 hour\n      expire: 86400,    \/\/ 1 day\n    },\n  },\n}\n\nexport default nextConfig<\/code><\/pre>\n<pre><code>\/\/ anywhere inside a 'use cache' scope\ncacheLife('editorial')\n\n\/\/ or inline (seconds)\ncacheLife({ stale: 60, revalidate: 300, expire: 3600 })<\/code><\/pre>\n<div class=\"dd-note\"><strong>Short-lived caches become dynamic holes.<\/strong> The <code>seconds<\/code> profile, <code>revalidate: 0<\/code>, or an <code>expire<\/code> under 5 minutes is excluded from the prerendered shell. Wrap such components in <code>&lt;Suspense&gt;<\/code>. Also, if you nest a short-lived cache inside another <code>'use cache'<\/code> that has no explicit <code>cacheLife<\/code>, Next.js throws during prerender, which is one more reason to always set it.<\/div>\n\n<h2 id=\"cachetag\">Step 5: cacheTag, updateTag and revalidateTag<\/h2>\n<p>Time-based refresh is fine for many pages, but when a user creates or edits something you want to refresh <em>now<\/em>. That is what tags are for. You tag cached data with <code>cacheTag()<\/code>, then invalidate by tag after a change.<\/p>\n\n<figure class=\"dd-fig\">\n<svg viewBox=\"0 0 900 360\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" font-family=\"Inter, Segoe UI, Arial, sans-serif\" role=\"img\" aria-label=\"Flow diagram: a mutation calls updateTag or revalidateTag, which invalidates cache entries tagged posts\">\n<rect x=\"0\" y=\"0\" width=\"900\" height=\"360\" fill=\"#0f1430\"\/>\n<text x=\"30\" y=\"38\" fill=\"#a9b8ff\" font-size=\"16\" font-weight=\"700\" letter-spacing=\"2\">ON-DEMAND INVALIDATION WITH TAGS<\/text>\n<g class=\"ddb-node\"><title>User submits a form handled by a Server Action<\/title>\n<rect x=\"30\" y=\"140\" width=\"170\" height=\"80\" rx=\"14\" fill=\"#1a2150\" stroke=\"#3178c6\" stroke-width=\"2\"\/>\n<text x=\"115\" y=\"175\" fill=\"#fff\" font-size=\"16\" font-weight=\"700\" text-anchor=\"middle\">Server Action<\/text>\n<text x=\"115\" y=\"198\" fill=\"#a9b8ff\" font-size=\"13\" text-anchor=\"middle\">createPost()<\/text><\/g>\n<g class=\"ddb-node\"><title>CMS calls a Route Handler webhook<\/title>\n<rect x=\"30\" y=\"250\" width=\"170\" height=\"70\" rx=\"14\" fill=\"#1a2150\" stroke=\"#f76707\" stroke-width=\"2\"\/>\n<text x=\"115\" y=\"280\" fill=\"#fff\" font-size=\"16\" font-weight=\"700\" text-anchor=\"middle\">Webhook<\/text>\n<text x=\"115\" y=\"301\" fill=\"#ffc9a3\" font-size=\"13\" text-anchor=\"middle\">route.ts<\/text><\/g>\n<path id=\"f1\" d=\"M200 170 H 330\" stroke=\"#12b886\" stroke-width=\"3\" fill=\"none\"\/>\n<path id=\"f2\" d=\"M200 285 C 270 285, 270 230, 330 230\" stroke=\"#f76707\" stroke-width=\"3\" fill=\"none\"\/>\n<circle r=\"6\" fill=\"#7ee787\"><animateMotion dur=\"1.6s\" repeatCount=\"indefinite\"><mpath href=\"#f1\"\/><\/animateMotion><\/circle>\n<circle r=\"6\" fill=\"#ffa94d\"><animateMotion dur=\"2.2s\" repeatCount=\"indefinite\"><mpath href=\"#f2\"\/><\/animateMotion><\/circle>\n<rect x=\"330\" y=\"140\" width=\"200\" height=\"40\" rx=\"10\" fill=\"#12b886\"\/>\n<text x=\"430\" y=\"166\" fill=\"#fff\" font-size=\"15\" font-weight=\"700\" text-anchor=\"middle\">updateTag(&#8216;posts&#8217;)<\/text>\n<rect x=\"315\" y=\"210\" width=\"230\" height=\"40\" rx=\"10\" fill=\"#f76707\"\/>\n<text x=\"430\" y=\"236\" fill=\"#fff\" font-size=\"14\" font-weight=\"700\" text-anchor=\"middle\">revalidateTag(&#8216;posts&#8217;,&#8217;max&#8217;)<\/text>\n<text x=\"430\" y=\"200\" fill=\"#c7cbe0\" font-size=\"12\" text-anchor=\"middle\">expire now \u00b7 read-your-writes<\/text>\n<text x=\"430\" y=\"270\" fill=\"#c7cbe0\" font-size=\"12\" text-anchor=\"middle\">serve stale \u00b7 refresh in background<\/text>\n<path d=\"M530 195 H 610\" stroke=\"#7c5cff\" stroke-width=\"3\" fill=\"none\"\/>\n<polygon points=\"610,188 624,195 610,202\" fill=\"#7c5cff\"\/>\n<rect x=\"630\" y=\"70\" width=\"240\" height=\"250\" rx=\"14\" fill=\"#151b3b\" stroke=\"#2c3570\"\/>\n<text x=\"750\" y=\"100\" fill=\"#a9b8ff\" font-size=\"14\" font-weight=\"700\" text-anchor=\"middle\">CACHE ENTRIES<\/text>\n<rect x=\"650\" y=\"115\" width=\"200\" height=\"40\" rx=\"8\" fill=\"#7c5cff\"\/><text x=\"750\" y=\"140\" fill=\"#fff\" font-size=\"13\" text-anchor=\"middle\">getPosts() \u00b7 tag: posts<\/text>\n<rect x=\"650\" y=\"165\" width=\"200\" height=\"40\" rx=\"8\" fill=\"#7c5cff\"\/><text x=\"750\" y=\"190\" fill=\"#fff\" font-size=\"13\" text-anchor=\"middle\">&lt;PostList\/&gt; \u00b7 tag: posts<\/text>\n<rect x=\"650\" y=\"215\" width=\"200\" height=\"40\" rx=\"8\" fill=\"#2c3570\"\/><text x=\"750\" y=\"240\" fill=\"#a9b8ff\" font-size=\"13\" text-anchor=\"middle\">getUsers() \u00b7 tag: users<\/text>\n<text x=\"750\" y=\"290\" fill=\"#7ee787\" font-size=\"13\" text-anchor=\"middle\">only &#8220;posts&#8221; entries refresh<\/text>\n<\/svg>\n<figcaption>Figure 2: Tags let you refresh exactly the cache entries affected by a change, nothing more.<\/figcaption>\n<\/figure>\n\n<h3>updateTag: the user should see their change immediately<\/h3>\n<p>Use <code>updateTag<\/code> inside a <strong>Server Action<\/strong> when the person who made the change must see it on the next screen (read-your-own-writes):<\/p>\n<span class=\"dd-file\">app\/blog\/actions.ts<\/span>\n<pre><code>'use server'\n\nimport { updateTag } from 'next\/cache'\nimport { redirect } from 'next\/navigation'\nimport { db } from '@\/app\/lib\/db'\n\nexport async function createPost(formData: FormData) {\n  const post = await db.post.create({\n    data: {\n      title: String(formData.get('title')),\n      content: String(formData.get('content')),\n    },\n  })\n\n  updateTag('posts')          \/\/ expire every entry tagged 'posts' right now\n  redirect(`\/blog\/${post.id}`)\n}<\/code><\/pre>\n<span class=\"dd-file\">app\/blog\/new\/page.tsx<\/span>\n<pre><code>import { createPost } from '..\/actions'\n\nexport default function NewPostPage() {\n  return (\n    &lt;form action={createPost}&gt;\n      &lt;input name=\"title\" placeholder=\"Title\" required \/&gt;\n      &lt;textarea name=\"content\" placeholder=\"Write something\u2026\" required \/&gt;\n      &lt;button type=\"submit\"&gt;Publish&lt;\/button&gt;\n    &lt;\/form&gt;\n  )\n}<\/code><\/pre>\n\n<h3>revalidateTag: refresh in the background<\/h3>\n<p>Use <code>revalidateTag<\/code> when a small delay is fine, for example when your CMS sends a webhook. It works in Server Actions <em>and<\/em> Route Handlers. In Next.js 16 the second argument (a cacheLife profile) is required; <code>'max'<\/code> is the recommended value.<\/p>\n<span class=\"dd-file\">app\/api\/revalidate\/route.ts<\/span>\n<pre><code>import { revalidateTag } from 'next\/cache'\nimport type { NextRequest } from 'next\/server'\n\nexport async function POST(request: NextRequest) {\n  const secret = request.headers.get('x-webhook-secret')\n  if (secret !== process.env.WEBHOOK_SECRET) {\n    return Response.json({ ok: false }, { status: 401 })\n  }\n\n  const { tag } = await request.json() \/\/ e.g. { \"tag\": \"posts\" }\n  revalidateTag(tag, 'max')            \/\/ stale-while-revalidate\n\n  return Response.json({ ok: true, revalidated: tag })\n}<\/code><\/pre>\n<p>Test it locally with curl:<\/p>\n<pre><code>curl -X POST http:\/\/localhost:3000\/api\/revalidate \\\n  -H \"Content-Type: application\/json\" \\\n  -H \"x-webhook-secret: $WEBHOOK_SECRET\" \\\n  -d '{\"tag\":\"posts\"}'<\/code><\/pre>\n<table>\n<thead><tr><th><\/th><th><code>updateTag<\/code><\/th><th><code>revalidateTag<\/code><\/th><th><code>revalidatePath<\/code><\/th><\/tr><\/thead>\n<tbody>\n<tr><td>Where<\/td><td>Server Actions only<\/td><td>Server Actions + Route Handlers<\/td><td>Server Actions + Route Handlers<\/td><\/tr>\n<tr><td>Behaviour<\/td><td>Expires immediately<\/td><td>Stale-while-revalidate<\/td><td>Everything for one path<\/td><\/tr>\n<tr><td>Use when<\/td><td>User must see own change<\/td><td>CMS\/webhook, slight delay OK<\/td><td>You don&#8217;t know the tags<\/td><\/tr>\n<\/tbody><\/table>\n<div class=\"dd-tip\"><strong>Tip:<\/strong> Prefer tags over paths. <code>revalidatePath('\/')<\/code> can throw away far more cache than you intended.<\/div>\n\n<h2 id=\"runtime\">Step 6: Cookies, headers and per-user data<\/h2>\n<p>You <strong>cannot<\/strong> call <code>cookies()<\/code>, <code>headers()<\/code> or read <code>searchParams<\/code> directly inside a plain <code>'use cache'<\/code> function, because the result would be shared between users. The recommended pattern is: read the runtime value outside, then pass it in as an argument. The argument becomes part of the cache key.<\/p>\n<span class=\"dd-file\">app\/profile\/page.tsx<\/span>\n<pre><code>import { Suspense } from 'react'\nimport { cookies } from 'next\/headers'\nimport { cacheLife } from 'next\/cache'\n\nexport default function ProfilePage() {\n  return (\n    &lt;Suspense fallback={&lt;p&gt;Loading profile\u2026&lt;\/p&gt;}&gt;\n      &lt;ProfileContent \/&gt;\n    &lt;\/Suspense&gt;\n  )\n}\n\n\/\/ Not cached: reads the cookie at request time\nasync function ProfileContent() {\n  const userId = (await cookies()).get('userId')?.value ?? 'guest'\n  return &lt;CachedProfile userId={userId} \/&gt;\n}\n\n\/\/ Cached per userId\nasync function CachedProfile({ userId }: { userId: string }) {\n  'use cache'\n  cacheLife('minutes')\n\n  const res = await fetch(`https:\/\/jsonplaceholder.typicode.com\/users\/1?u=${userId}`)\n  const user = await res.json()\n  return &lt;h2&gt;Hello, {user.name}&lt;\/h2&gt;\n}<\/code><\/pre>\n<p>Next.js 16 also ships two variants of the directive for special cases:<\/p>\n<ul>\n<li><code>'use cache: private'<\/code> \u2013 can read cookies\/headers directly; the result is cached only in that user&#8217;s browser (great for prefetching personalised UI).<\/li>\n<li><code>'use cache: remote'<\/code> \u2013 stores entries in a shared, durable cache handler instead of per-instance memory. Useful on serverless platforms, where in-memory entries don&#8217;t survive between requests.<\/li>\n<\/ul>\n<p>Need a truly unique value per request, like a request ID or the current time? Call <code>connection()<\/code> first and wrap the component in Suspense:<\/p>\n<pre><code>import { connection } from 'next\/server'\n\nasync function RequestId() {\n  await connection() \/\/ defer to request time\n  return &lt;p&gt;Request ID: {crypto.randomUUID()}&lt;\/p&gt;\n}<\/code><\/pre>\n<p>If you are new to async patterns like these, our guide on <a href=\"https:\/\/devdojo.co.in\/index.php\/2024\/08\/12\/mastering-javascript-promises-a-guide-to-asynchronous-programming\/\">mastering JavaScript Promises<\/a> is a good refresher, since Server Components are just async functions under the hood.<\/p>\n<\/div>\n\n\n\n<div class=\"dd-post\">\n<h2 id=\"which-tool\">Interactive: which caching tool should I use?<\/h2>\n<p>Click a tab to match your data to the right pattern.<\/p>\n<div class=\"dd-tabs-box\">\n<input type=\"radio\" name=\"ddtabs\" id=\"ddt1\" checked>\n<input type=\"radio\" name=\"ddtabs\" id=\"ddt2\">\n<input type=\"radio\" name=\"ddtabs\" id=\"ddt3\">\n<input type=\"radio\" name=\"ddtabs\" id=\"ddt4\">\n<div class=\"dd-tabbar\">\n<label for=\"ddt1\">Same for everyone<\/label>\n<label for=\"ddt2\">Changes after a form<\/label>\n<label for=\"ddt3\">Different per user<\/label>\n<label for=\"ddt4\">Must be live<\/label>\n<\/div>\n<div class=\"dd-panel dd-p1\">\n<h4>Public content: blog posts, product catalogue, docs<\/h4>\n<p>Use <code>'use cache'<\/code> + <code>cacheLife('days')<\/code> (or <code>'max'<\/code> for CMS content) + <code>cacheTag()<\/code>. Trigger <code>revalidateTag(tag, 'max')<\/code> from a webhook when content changes. Result: served from the static shell, refreshed only when needed.<\/p>\n<\/div>\n<div class=\"dd-panel dd-p2\">\n<h4>User-generated content: comments, posts, settings<\/h4>\n<p>Cache reads with <code>'use cache'<\/code> + <code>cacheTag('comments')<\/code>. In the Server Action that saves the data, call <code>updateTag('comments')<\/code> so the author sees the change on the very next render.<\/p>\n<\/div>\n<div class=\"dd-panel dd-p3\">\n<h4>Personalised UI: dashboard, cart, profile<\/h4>\n<p>Read <code>cookies()<\/code> inside a component wrapped in <code>&lt;Suspense&gt;<\/code>, then pass the user ID to a cached child (cache key per user). Or use <code>'use cache: private'<\/code> for browser-only caching that can be prefetched.<\/p>\n<\/div>\n<div class=\"dd-panel dd-p4\">\n<h4>Real-time data: stock prices, live scores, request IDs<\/h4>\n<p>Don&#8217;t cache at all, or use <code>cacheLife('seconds')<\/code>. Put the component inside <code>&lt;Suspense&gt;<\/code> with a good fallback. Use <code>await connection()<\/code> before <code>Date.now()<\/code>, <code>Math.random()<\/code> or <code>crypto.randomUUID()<\/code>.<\/p>\n<\/div>\n<\/div>\n\n<h2 id=\"errors\">Common errors and fixes<\/h2>\n<table>\n<thead><tr><th>Error \/ symptom<\/th><th>Why it happens<\/th><th>Fix<\/th><\/tr><\/thead>\n<tbody>\n<tr><td><em>Uncached data was accessed outside of &lt;Suspense&gt;<\/em> (shown as a &#8220;blocking-route&#8221; insight in 16.3)<\/td><td>A component fetches fresh data or reads cookies\/headers with no Suspense boundary above it.<\/td><td>Wrap it in <code>&lt;Suspense fallback={...}&gt;<\/code>, or cache it with <code>'use cache'<\/code>.<\/td><\/tr>\n<tr><td>Error using <code>cookies()<\/code> \/ <code>headers()<\/code> inside <code>'use cache'<\/code><\/td><td>Runtime APIs can&#8217;t run in a shared cache scope.<\/td><td>Read the value outside and pass it as an argument, or use <code>'use cache: private'<\/code>.<\/td><\/tr>\n<tr><td>&#8220;blocking-prerender-current-time&#8221; \/ &#8220;-random&#8221; \/ &#8220;-crypto&#8221;<\/td><td><code>Date.now()<\/code>, <code>Math.random()<\/code> or <code>crypto.randomUUID()<\/code> during prerender.<\/td><td><code>await connection()<\/code> + Suspense, or move it inside <code>'use cache'<\/code> if one shared value is fine.<\/td><\/tr>\n<tr><td>Error about <code>export const revalidate<\/code> \/ <code>dynamic<\/code><\/td><td>Route segment configs are replaced by Cache Components.<\/td><td>Delete them; use <code>cacheLife()<\/code> in the cached scope instead.<\/td><\/tr>\n<tr><td>Data never updates after saving<\/td><td>No tag on the cached function, or tag names don&#8217;t match.<\/td><td>Add <code>cacheTag('x')<\/code> and call <code>updateTag('x')<\/code> with the exact same string.<\/td><\/tr>\n<tr><td>Error during prerender about nested short-lived cache<\/td><td>A <code>cacheLife('seconds')<\/code> component is used inside a <code>'use cache'<\/code> scope with no explicit <code>cacheLife<\/code>.<\/td><td>Add an explicit <code>cacheLife()<\/code> to the outer scope.<\/td><\/tr>\n<tr><td>Cache seems to reset on every request (serverless)<\/td><td>Default runtime cache is in-memory per instance.<\/td><td>Use <code>'use cache: remote'<\/code> with a configured cache handler for high hit-rate data.<\/td><\/tr>\n<tr><td>&#8220;Only plain objects can be passed\u2026&#8221; style serialization errors<\/td><td>Passing a class instance or function as a cached argument \/ return value.<\/td><td>Pass IDs or plain objects; return plain JSON-like data.<\/td><\/tr>\n<\/tbody><\/table>\n\n<h2 id=\"best-practices\">Best practices<\/h2>\n<ul class=\"dd-check\">\n<li><strong>Always call <code>cacheLife()<\/code><\/strong> in every <code>'use cache'<\/code> scope, right at the top. It makes behaviour obvious to the next developer.<\/li>\n<li><strong>Tag generously, invalidate narrowly.<\/strong> Use a broad tag (<code>'posts'<\/code>) and a specific one (<code>`post-${id}`<\/code>) on the same entry.<\/li>\n<li><strong>Push dynamic work deep down the tree.<\/strong> The lower your <code>cookies()<\/code> or uncached fetch sits, the more of the page stays in the static shell.<\/li>\n<li><strong>Keep cached return values small.<\/strong> Return only the fields the UI needs, not whole ORM objects.<\/li>\n<li><strong>Don&#8217;t cache per-user data in a shared scope<\/strong> unless the user ID is an argument. Never leak one user&#8217;s data to another.<\/li>\n<li><strong>Use <code>updateTag<\/code> for forms, <code>revalidateTag(tag, 'max')<\/code> for webhooks.<\/strong> Avoid the old single-argument <code>revalidateTag(tag)<\/code>; it is deprecated in Next.js 16.<\/li>\n<li><strong>Write good Suspense fallbacks.<\/strong> Skeletons that match the final layout prevent layout shift and improve Core Web Vitals.<\/li>\n<li><strong>Check the dev overlay.<\/strong> In 16.3, Instant Insights and the Navigation Inspector show exactly which parts are blocking.<\/li>\n<\/ul>\n\n<h3>Migrating from the old caching model<\/h3>\n<table>\n<thead><tr><th>Old (Next.js 14\/15)<\/th><th>New (Cache Components)<\/th><\/tr><\/thead>\n<tbody>\n<tr><td><code>fetch(url, { next: { revalidate: 3600 } })<\/code><\/td><td>Wrap the fetch in a <code>'use cache'<\/code> function with <code>cacheLife('hours')<\/code><\/td><\/tr>\n<tr><td><code>fetch(url, { next: { tags: ['posts'] } })<\/code><\/td><td><code>cacheTag('posts')<\/code> inside the cached function<\/td><\/tr>\n<tr><td><code>unstable_cache(fn, keys, opts)<\/code><\/td><td><code>'use cache'<\/code> directive inside <code>fn<\/code><\/td><\/tr>\n<tr><td><code>export const revalidate = 60<\/code><\/td><td><code>cacheLife({ revalidate: 60 })<\/code><\/td><\/tr>\n<tr><td><code>export const dynamic = 'force-dynamic'<\/code><\/td><td>Default behaviour; just use Suspense<\/td><\/tr>\n<\/tbody><\/table>\n<p>The official <a href=\"https:\/\/nextjs.org\/docs\/app\/getting-started\/caching\" target=\"_blank\" rel=\"noopener\">Next.js caching documentation<\/a> and the <a href=\"https:\/\/nextjs.org\/docs\/app\/api-reference\/functions\/cacheLife\" target=\"_blank\" rel=\"noopener\">cacheLife API reference<\/a> have more detail and a step-by-step migration guide.<\/p>\n\n<h2 id=\"faq\">FAQ<\/h2>\n<details class=\"dd-faq\"><summary>Is &#8220;use cache&#8221; stable in Next.js 16?<\/summary>\n<p>Yes. Cache Components and the <code>'use cache'<\/code> directive shipped as a stable, opt-in feature in Next.js 16.0 and were extended in 16.3. You enable it with <code>cacheComponents: true<\/code>.<\/p><\/details>\n<details class=\"dd-faq\"><summary>Do I still need to cache fetch() calls?<\/summary>\n<p>With Cache Components, <code>fetch<\/code> is not cached by default. If you want a fetch result reused, put it inside a function or component marked with <code>'use cache'<\/code>.<\/p><\/details>\n<details class=\"dd-faq\"><summary>What is the difference between updateTag and revalidateTag?<\/summary>\n<p><code>updateTag<\/code> expires the cache immediately and works only in Server Actions, so the user sees their own change. <code>revalidateTag(tag, 'max')<\/code> serves stale data while refreshing in the background and also works in Route Handlers.<\/p><\/details>\n<details class=\"dd-faq\"><summary>Can I use &#8220;use cache&#8221; in a Client Component?<\/summary>\n<p>No. It runs on the server. You can cache a Server Component and render Client Components inside it, or pass cached data down to them as props.<\/p><\/details>\n<details class=\"dd-faq\"><summary>Where is the cache stored?<\/summary>\n<p>Prerendered results live in the static shell (on disk or your host&#8217;s CDN). Runtime entries live in memory per server instance by default, <code>'use cache: remote'<\/code> uses a shared cache handler, and <code>'use cache: private'<\/code> lives only in the browser. All caches are scoped to one deployment.<\/p><\/details>\n<details class=\"dd-faq\"><summary>Does this work when self-hosting on a VPS or Docker?<\/summary>\n<p>Yes. On a long-running Node.js server the in-memory cache persists between requests, so plain <code>'use cache'<\/code> works well. For multiple instances, configure a shared cache handler.<\/p><\/details>\n\n<h2>Conclusion<\/h2>\n<p>The Next.js use cache directive turns caching from guesswork into a clear, readable decision in your code. Turn on <code>cacheComponents<\/code>, mark slow and shareable work with <code>'use cache'<\/code>, give it a lifetime with <code>cacheLife<\/code>, label it with <code>cacheTag<\/code>, and put everything request-specific behind <code>&lt;Suspense&gt;<\/code>. Do that, and your pages load from a static shell instantly while still showing fresh data exactly where it matters.<\/p>\n<p>A good next step: take one slow page in your project, split it into static, cached and dynamic parts like Figure 1, and measure the difference. And if you are also exploring AI tooling, check out our hands-on guide on <a href=\"https:\/\/devdojo.co.in\/index.php\/2026\/10\/03\/build-mcp-server-typescript\/\">how to build an MCP server in TypeScript<\/a>.<\/p>\n\n<div class=\"dd-cta\">\n<h3>New posts every day on DevDojo<\/h3>\n<p>Practical tutorials on React, Next.js, Node.js, Python, AI and interview prep, written in simple English.<\/p>\n<p>Bookmark DevDojo and drop your Cache Components questions in the comments below.<\/p>\n<a href=\"https:\/\/devdojo.co.in\/\">Explore more tutorials \u2192<\/a>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples.<\/p>\n","protected":false},"author":1,"featured_media":166,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,6,4],"tags":[47,46,50,48,49],"class_list":["post-167","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-frontend","category-nextjs","category-reactjs","tag-caching","tag-next-js","tag-next-js-16","tag-react-server-components","tag-web-performance"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Lokendra\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"DevDojo - Empowering Developers\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Next.js use cache Explained: Cache Components, cacheLife &amp; cacheTag\" \/>\n\t\t<meta property=\"og:description\" content=\"Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-10-05T04:44:46+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-10-05T04:44:46+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Next.js use cache Explained: Cache Components, cacheLife &amp; cacheTag\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples.\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BlogPosting\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#blogposting\",\"name\":\"Next.js use cache Explained: Cache Components Guide\",\"headline\":\"Next.js use cache Explained: Cache Components, cacheLife &#038; cacheTag (2026 Guide)\",\"author\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/author\\\/lokendra\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/nextjs-use-cache.jpg\",\"width\":1200,\"height\":630,\"caption\":\"Next.js use cache explained: Cache Components, cacheLife and cacheTag banner\"},\"datePublished\":\"2026-10-05T04:44:46+00:00\",\"dateModified\":\"2026-10-05T04:44:46+00:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#webpage\"},\"articleSection\":\"Frontend, NextJS, ReactJS, Caching, Next.js, Next.js 16, React Server Components, Web Performance\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/devdojo.co.in\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/frontend\\\/#listItem\",\"name\":\"Frontend\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/frontend\\\/#listItem\",\"position\":2,\"name\":\"Frontend\",\"item\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/frontend\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/frontend\\\/reactjs\\\/#listItem\",\"name\":\"ReactJS\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/frontend\\\/reactjs\\\/#listItem\",\"position\":3,\"name\":\"ReactJS\",\"item\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/frontend\\\/reactjs\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#listItem\",\"name\":\"Next.js use cache Explained: Cache Components, cacheLife &#038; cacheTag (2026 Guide)\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/frontend\\\/#listItem\",\"name\":\"Frontend\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#listItem\",\"position\":4,\"name\":\"Next.js use cache Explained: Cache Components, cacheLife &#038; cacheTag (2026 Guide)\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/category\\\/frontend\\\/reactjs\\\/#listItem\",\"name\":\"ReactJS\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#organization\",\"name\":\"DevDojo\",\"description\":\"Empowering Developers\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/author\\\/lokendra\\\/#author\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/author\\\/lokendra\\\/\",\"name\":\"Lokendra\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/99f102f0cc9080237ce54b91304fd1b3b6fa29925cbaeba93cd796872e58b45c?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Lokendra\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#webpage\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/\",\"name\":\"Next.js use cache Explained: Cache Components Guide\",\"description\":\"Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples.\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/author\\\/lokendra\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/author\\\/lokendra\\\/#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/nextjs-use-cache.jpg\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#mainImage\",\"width\":1200,\"height\":630,\"caption\":\"Next.js use cache explained: Cache Components, cacheLife and cacheTag banner\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/index.php\\\/2026\\\/10\\\/05\\\/nextjs-use-cache\\\/#mainImage\"},\"datePublished\":\"2026-10-05T04:44:46+00:00\",\"dateModified\":\"2026-10-05T04:44:46+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#website\",\"url\":\"https:\\\/\\\/devdojo.co.in\\\/\",\"name\":\"DevDojo\",\"description\":\"Empowering Developers\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/devdojo.co.in\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Next.js use cache Explained: Cache Components Guide","description":"Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples.","canonical_url":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BlogPosting","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#blogposting","name":"Next.js use cache Explained: Cache Components Guide","headline":"Next.js use cache Explained: Cache Components, cacheLife &#038; cacheTag (2026 Guide)","author":{"@id":"https:\/\/devdojo.co.in\/index.php\/author\/lokendra\/#author"},"publisher":{"@id":"https:\/\/devdojo.co.in\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/devdojo.co.in\/wp-content\/uploads\/2026\/10\/nextjs-use-cache.jpg","width":1200,"height":630,"caption":"Next.js use cache explained: Cache Components, cacheLife and cacheTag banner"},"datePublished":"2026-10-05T04:44:46+00:00","dateModified":"2026-10-05T04:44:46+00:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#webpage"},"isPartOf":{"@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#webpage"},"articleSection":"Frontend, NextJS, ReactJS, Caching, Next.js, Next.js 16, React Server Components, Web Performance"},{"@type":"BreadcrumbList","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/#listItem","position":1,"name":"Home","item":"https:\/\/devdojo.co.in\/","nextItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/#listItem","name":"Frontend"}},{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/#listItem","position":2,"name":"Frontend","item":"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/","nextItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/reactjs\/#listItem","name":"ReactJS"},"previousItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/reactjs\/#listItem","position":3,"name":"ReactJS","item":"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/reactjs\/","nextItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#listItem","name":"Next.js use cache Explained: Cache Components, cacheLife &#038; cacheTag (2026 Guide)"},"previousItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/#listItem","name":"Frontend"}},{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#listItem","position":4,"name":"Next.js use cache Explained: Cache Components, cacheLife &#038; cacheTag (2026 Guide)","previousItem":{"@type":"ListItem","@id":"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/reactjs\/#listItem","name":"ReactJS"}}]},{"@type":"Organization","@id":"https:\/\/devdojo.co.in\/#organization","name":"DevDojo","description":"Empowering Developers","url":"https:\/\/devdojo.co.in\/"},{"@type":"Person","@id":"https:\/\/devdojo.co.in\/index.php\/author\/lokendra\/#author","url":"https:\/\/devdojo.co.in\/index.php\/author\/lokendra\/","name":"Lokendra","image":{"@type":"ImageObject","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/99f102f0cc9080237ce54b91304fd1b3b6fa29925cbaeba93cd796872e58b45c?s=96&d=mm&r=g","width":96,"height":96,"caption":"Lokendra"}},{"@type":"WebPage","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#webpage","url":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/","name":"Next.js use cache Explained: Cache Components Guide","description":"Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples.","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/devdojo.co.in\/#website"},"breadcrumb":{"@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#breadcrumblist"},"author":{"@id":"https:\/\/devdojo.co.in\/index.php\/author\/lokendra\/#author"},"creator":{"@id":"https:\/\/devdojo.co.in\/index.php\/author\/lokendra\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/devdojo.co.in\/wp-content\/uploads\/2026\/10\/nextjs-use-cache.jpg","@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#mainImage","width":1200,"height":630,"caption":"Next.js use cache explained: Cache Components, cacheLife and cacheTag banner"},"primaryImageOfPage":{"@id":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/#mainImage"},"datePublished":"2026-10-05T04:44:46+00:00","dateModified":"2026-10-05T04:44:46+00:00"},{"@type":"WebSite","@id":"https:\/\/devdojo.co.in\/#website","url":"https:\/\/devdojo.co.in\/","name":"DevDojo","description":"Empowering Developers","inLanguage":"en-US","publisher":{"@id":"https:\/\/devdojo.co.in\/#organization"}}]},"og:locale":"en_US","og:site_name":"DevDojo - Empowering Developers","og:type":"article","og:title":"Next.js use cache Explained: Cache Components, cacheLife &amp; cacheTag","og:description":"Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples.","og:url":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/","article:published_time":"2026-10-05T04:44:46+00:00","article:modified_time":"2026-10-05T04:44:46+00:00","twitter:card":"summary_large_image","twitter:title":"Next.js use cache Explained: Cache Components, cacheLife &amp; cacheTag","twitter:description":"Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples."},"aioseo_meta_data":{"post_id":"167","title":"Next.js use cache Explained: Cache Components Guide","description":"Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples.","keywords":null,"keyphrases":{"focus":{"keyphrase":"Next.js use cache","score":82},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":"Next.js use cache Explained: Cache Components, cacheLife & cacheTag","og_description":"Learn the Next.js use cache directive step by step: enable Cache Components, use cacheLife, cacheTag, updateTag and revalidateTag with runnable 16.3 examples.","og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"BlogPosting","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":0,"frequency":"default","local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"created":"2026-10-05 04:41:07","updated":"2026-10-05 06:31:45","focus_keyword":"Next.js use cache","additional_keywords":null,"truseo_locale":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/devdojo.co.in\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/\" title=\"Frontend\">Frontend<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/reactjs\/\" title=\"ReactJS\">ReactJS<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tNext.js use cache Explained: Cache Components, cacheLife &amp; cacheTag (2026 Guide)\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/devdojo.co.in\/"},{"label":"Frontend","link":"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/"},{"label":"ReactJS","link":"https:\/\/devdojo.co.in\/index.php\/category\/frontend\/reactjs\/"},{"label":"Next.js use cache Explained: Cache Components, cacheLife &#038; cacheTag (2026 Guide)","link":"https:\/\/devdojo.co.in\/index.php\/2026\/10\/05\/nextjs-use-cache\/"}],"_links":{"self":[{"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/posts\/167","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/comments?post=167"}],"version-history":[{"count":1,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/posts\/167\/revisions"}],"predecessor-version":[{"id":168,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/posts\/167\/revisions\/168"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/media\/166"}],"wp:attachment":[{"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/media?parent=167"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/categories?post=167"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devdojo.co.in\/index.php\/wp-json\/wp\/v2\/tags?post=167"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}