{"id":3316,"date":"2025-04-09T14:57:13","date_gmt":"2025-04-09T12:57:13","guid":{"rendered":"https:\/\/uniquedevs.com\/blog\/jak-dziala-cache-w-next-js-15-praktyczne-wprowadzenie-z-przykladami\/"},"modified":"2025-04-11T09:43:46","modified_gmt":"2025-04-11T07:43:46","slug":"how-does-caching-work-in-next-js-15","status":"publish","type":"post","link":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/","title":{"rendered":"How does caching work in Next.js 15? A practical introduction with examples"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Why is cache so important?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Caching is a technique that allows an application to remember previously downloaded data and avoid unnecessary network queries or costly calculations. A well-designed cache can dramatically speed up page loading and reduce server load. But caching also has its dark side: out-of-date data, erroneous revalidations and loss of control over what refreshes when.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/uniquedevs.com\/blog\/co-to-jest-next-js\/\">Next.js<\/a> until version 14 used by default mechanisms that automatically cached data from <code>fetch<\/code>. The problem was that this often led to unexpected results &#8211; especially in dynamic applications. In Next.js 15, the philosophy changes: by default, the cache is disabled, and the responsibility for making it work rests with the developer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This approach gives more control, but requires an understanding of how the new model works and when it is worth using it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">New caching model in Next.js 15 &#8211; what has changed?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The biggest change is that asynchronous functions are no longer cached by default. In previous versions, when you used <code>fetch<\/code> in a server component, Next.js could automatically cache the data and serve it as static. From now on, for something to be cached, you must explicitly declare it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What does this mean in practice?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Example &#8211; suppose you have a function that retrieves data from an API:<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>async function getUser(id: string) {\n  const res = await fetch(`https:\/\/api.example.com\/users\/${id}`);\n  return res.json();\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In Next.js 14, this function could be automatically cached. In Next.js 15 &#8211; <strong>no<\/strong>. The data will be fetched anew with each request, unless you give a signal that you want to cache it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To restart the caching mechanism &#8211; you use the new <code>'use cache'<\/code> directive (more about it in a moment).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">New: <code>dynamicIO<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Next.js 15 also introduces an experimental mode called <strong>dynamicIO<\/strong>, which changes the way the framework treats dynamic functions. By default, Next.js considers everything dynamic (i.e., requiring SSR), but with <code>dynamicIO<\/code> you can mark specific parts of your application as cache-safe or even static &#8211; giving you big performance gains.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To activate it, simply add to <code>next.config.js<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>experimental: {\n  serverActions: true,\n  dynamicIO: true\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This opens the door to deeper management of what is dynamic and what is not &#8211; and achieves a balance between data freshness and performance.<\/p>\n\n\n                        <div class=\"contact-banner purple\" >\n                <div class=\"contact-banner__image\">\n                    <img decoding=\"async\" src=\"https:\/\/uniquedevs.com\/wp-content\/themes\/uniquedevs\/assets\/images\/purple.webp\" alt=\"Looking for a trusted IT project contractor?\">\n                <\/div>\n                <div class=\"contact-banner__image-mobile\">\n                    <img decoding=\"async\" src=\"https:\/\/uniquedevs.com\/wp-content\/themes\/uniquedevs\/assets\/images\/purple-mobile.webp\" alt=\"Looking for a trusted IT project contractor?\">\n                <\/div>\n                <div class=\"contact-banner__wprapper\">\n                                            <div class=\"contact-banner__wrapper-title\">\n                            Looking for a trusted IT project contractor?                        <\/div>\n                                                                                            <a href=\"https:\/\/uniquedevs.com\/en\/contact\/\" class=\"contact-banner__wrapper-btn\" >\n                                Write to us!                            <\/a>\n                                                            <\/div>\n            <\/div>\n            \n\n\n<h2 class=\"wp-block-heading\">Directive <code>'use cache'<\/code> &#8211; full control over cache<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The new <code>'use cache'<\/code> directive is one of the most important tools in Next.js 15. It allows us to explicitly specify which functions should be cached &#8211; and for how long.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How does <code>'use cache'<\/code> work ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It is simply a special line added at the beginning of a file (or function) that says: &#8220;this function is to be cached&#8221;.<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>'use cache';\n\nexport async function getUser(id: string) {\n  const res = await fetch(`https:\/\/api.example.com\/users\/${id}`);\n  return res.json();\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">From this point on, <code>getUser<\/code> becomes a function whose result is stored in a cache and is not queried again with each request &#8211; until it is invalidated or the cache lifetime (if we have defined one) expires.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Where can you <code>use 'use cache'<\/code>?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use cache can be used in:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; in asynchronous functions<br>&#8211; in server components<br>&#8211; in data loader helpers<br>&#8211; at the level of entire layouts or pages<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example with component:<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>'use cache';\n\nexport default async function Profile({ userId }: { userId: string }) {\n  const user = await getUser(userId); \/\/ also with 'use cache'\n  return &lt;div&gt;{user.name}&lt;\/div&gt;;\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In this case, the component and the <code>getUser<\/code> function are cached, which means that user data will be retrieved only once for the life of the cache.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring the Next.js 15 project with <code>dynamicIO<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Next.js 15 introduces a new mechanism called <code>dynamicIO<\/code>, which allows for more precise management of what can be cached and what should remain dynamic. This tool not only improves performance, but also simplifies complex scenarios where some data can be static and some dynamic &#8211; and within a single page or component.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How to enable <code>dynamicIO<\/code>?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To activate <code>dynamicIO<\/code>, you need to add the appropriate flag in the file <code>next.config.js<\/code>. In practice, it looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ next.config.js\n\/** @type {import('next').NextConfig} *\/\nconst nextConfig = {\n  experimental: {\n    serverActions: true,\n    dynamicIO: true,\n  },\n};\n\nmodule.exports = nextConfig;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Practical note<\/strong>:<code> dynamicIO<\/code> only works in <strong>applications using the App Router<\/strong> (<code>\/app<\/code>), not with the older Pages Router<code>(\/pages<\/code>). It&#8217;s also worth making sure you have an up-to-date version of Next.js 15 and Node 18+.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What does <code>dynamicIO<\/code> change ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Bottom line:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>allows Next.js to analyze data flow at compile time.<\/li>\n\n\n\n<li>enables <code>'use cache'<\/code> to be used optimally &#8211; the framework knows which functions can be safely cached.<\/li>\n\n\n\n<li>avoids accidental <a href=\"https:\/\/uniquedevs.com\/en\/blog\/what-is-server-side-rendering\/\">SSR<\/a> &#8211; which has often been a problem in the past (e.g. by accidental use of <code>headers()<\/code> or <code>cookies()<\/code>).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">A practical example<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose you have a page <code>\/blog\/[slug]<\/code>, which displays a post based on the slug. You want the content of the post to be cached (because it rarely changes), but the comments to be always up-to-date (i.e. dynamic).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Catalog structure:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>app\/\n \u2514\u2500\u2500 blog\/\n      \u2514\u2500\u2500 &#91;slug]\/\n            \u2514\u2500\u2500 page.tsx\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>getPost.ts<\/code> (cached function):<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>'use cache';\n\nexport async function getPost(slug: string) {\n  const res = await fetch(`https:\/\/cms.example.com\/api\/posts\/${slug}`);\n  if (!res.ok) throw new Error('Post not found');\n  return res.json();\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>getComments.ts<\/code> (always dynamic):<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>export async function getComments(slug: string) {\n  const res = await fetch(`https:\/\/cms.example.com\/api\/comments\/${slug}`, {\n    cache: 'no-store', \/\/ enforcing no cache\n  });\n  return res.json();\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>page.tsx<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>import { getPost } from '@\/lib\/getPost';\nimport { getComments } from '@\/lib\/getComments';\n\nexport default async function BlogPage({ params }: { params: { slug: string } }) {\n  const post = await getPost(params.slug);      \/\/ using cache\n  const comments = await getComments(params.slug);  \/\/ dynamic\n\n  return (\n    &lt;article&gt;\n      &lt;h1&gt;{post.title}&lt;\/h1&gt;\n      &lt;p&gt;{post.content}&lt;\/p&gt;\n\n      &lt;section&gt;\n        &lt;h2&gt;Komentarze&lt;\/h2&gt;\n        &lt;ul&gt;\n          {comments.map((c) =&gt; (\n            &lt;li key={c.id}&gt;{c.text}&lt;\/li&gt;\n          ))}\n        &lt;\/ul&gt;\n      &lt;\/section&gt;\n    &lt;\/article&gt;\n  );\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The effect<\/strong>: The website will be generated faster because the main content is cached, but the user will always see the latest comments.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Tip:<\/strong>&nbsp;When you have a lot of data to cache, make sure you separate the layers:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; component (<code>page.tsx<\/code>) &#8211; merges this data<br>This division allows you to test and debug cache behavior without unnecessary chaos in the view logic.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; data layer (<code>lib\/get*.ts<\/code>) \u2013 you mark&nbsp;<code>'use cache'<\/code>&nbsp;or not<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Cache in practice \u2013 Next.js 15 integration with local API<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You don&#8217;t need to use external services or a complicated backend to test how the cache works in Next.js 15. All you need is a local API endpoint that returns data \u2013 e.g. a list of products. This is enough to demonstrate how&nbsp;<code>'use cache'<\/code>, revalidation and how Next.js stores data at the server level work.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s assume you are building a product page. The data comes from the local endpoint&nbsp;<code>\/api\/products<\/code>, which returns a list of products from a JSON file (we are simulating the backend here).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. API with product data (<code>\/api\/products\/route.ts<\/code>)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s start with the local endpoint that provides the product list. This will be our data source &#8211; a simulation of the backend. We return the data in JSON format.<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ app\/api\/products\/route.ts\nimport { NextResponse } from 'next\/server';\n\nconst products = &#91;\n  { id: 1, name: 'Laptop', price: 4500 },\n  { id: 2, name: 'Keyboard', price: 350 },\n  { id: 3, name: 'Mouce', price: 150 },\n];\n\nexport async function GET() {\n  return NextResponse.json(products);\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. Function that retrieves data from the API<code>(lib\/getProducts.ts<\/code>)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">We create a separate function for retrieving data. It is in it that we will mark the cache with <code>'use cache'<\/code> and specify the revalidation time.<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ lib\/getProducts.ts\n'use cache';\n\nexport async function getProducts() {\n  const res = await fetch('http:\/\/localhost:3000\/api\/products', {\n    next: { revalidate: 60 }, \/\/ cache na 60 seconds\n  });\n  return res.json();\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. Product list page<code>(app\/products\/page.tsx<\/code>)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Finally &#8211; a page that uses our function and displays data in the UI. The data will be fetched only once every 60 seconds (thanks to the cache), and then served from memory.<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ app\/products\/page.tsx\nimport { getProducts } from '@\/lib\/getProducts';\n\nexport default async function ProductsPage() {\n  const products = await getProducts();\n\n  return (\n    &lt;section&gt;\n      &lt;h1&gt;Our Products&lt;\/h1&gt;\n      &lt;ul&gt;\n        {products.map((p) =&gt; (\n          &lt;li key={p.id}&gt;\n            {p.name} \u2013 {p.price} z\u0142\n          &lt;\/li&gt;\n        ))}\n      &lt;\/ul&gt;\n    &lt;\/section&gt;\n  );\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Users visiting the site at short intervals will see the cached data, which will speed up loading and reduce server load.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Managing cache lifetime and data revalidation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Simply caching data is just the beginning. In real applications, we need ways to determine when data should refresh and be able to control it in a precise and predictable manner.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next.js 15 introduces several mechanisms that allow you to manage the cache life cycle:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>revalidate<\/code>&nbsp;\u2013 data retention time (e.g. 60 seconds),<\/li>\n\n\n\n<li><code>cacheTag<\/code>&nbsp;\u2013 tagging of cached data,<\/li>\n\n\n\n<li><code>revalidateTag<\/code>&nbsp;\u2013 dynamic invalidation of data on the server side.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Below, we will go through each of these mechanisms with practical examples.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1.&nbsp;<code>revalidate<\/code>\u2013 cache lifetime of data<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;<code>revalidate<\/code>&nbsp;field determines how long (in seconds) the result of a&nbsp;<code>fetch<\/code>should be stored in the cache before it is fetched again.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Example:<\/h4>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ lib\/getNews.ts\n'use cache';\n\nexport async function getNews() {\n  const res = await fetch('https:\/\/api.example.com\/news', {\n    next: { revalidate: 120 }, \/\/ cache for 2 minutes\n  });\n  return res.json();\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This means: the data is cached for 2 minutes. After this time, Next.js can download a fresh version, but the old version can still be served until updated &#8211; the so-called constant-while-revalidate.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tip: use revalidate for data that rarely changes, such as blog posts, products, categories.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>2. CacheTag &#8211; tagging cached data.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When you want to group and control the cache for related data (e.g. all blog posts), you can assign tags to them.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Example:<\/h4>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ lib\/getPosts.ts\n'use cache';\n\nexport async function getPosts() {\n  const res = await fetch('https:\/\/api.example.com\/posts', {\n    next: {\n      tags: &#91;'posts'], \/\/ we assign the tag\n    },\n  });\n  return res.json();\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This makes Next.js save the result of this query with the label <code>\"posts\"<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. <code>revalidateTag<\/code> &#8211; dynamic cache invalidation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">And now the best part: you can remotely invalidate the cache with a specific tag. This is especially useful if your application has an admin panel from which you edit data.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Example:<\/h4>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ app\/api\/revalidate\/posts\/route.ts\nimport { revalidateTag } from 'next\/cache';\nimport { NextResponse } from 'next\/server';\n\nexport async function POST() {\n  revalidateTag('posts'); \/\/ invalidate all fetches with 'posts' tag\n  return NextResponse.json({ success: true });\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now when a user publishes a new post, you can call this API from either the admin panel or the webhook &#8211; and Next.js will remove the corresponding post from the cache and fetch fresh data on the next request.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Practical examples &#8211; caching in layouts, components and functions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Next.js 15 allows you to use cache not only in functions like <code>fetch<\/code>, but also in server components, page layouts and even in asynchronous &#8216;helpers&#8217;. In this section, you will see how to effectively implement <code>'use cache'<\/code> at different levels of application architecture.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Layout-level caching &#8211; ideal for repetitive content<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Layouts in App Router are a natural place to use cache, as they often contain <strong>fixed structures<\/strong> such as headers, footers, sidebars or menus.<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ app\/(main)\/layout.tsx\n'use cache';\n\nimport { getMenuItems } from '@\/lib\/getMenuItems';\n\nexport default async function MainLayout({ children }: { children: React.ReactNode }) {\n  const menu = await getMenuItems(); \/\/ cached function\n\n  return (\n    &lt;div&gt;\n      &lt;nav&gt;\n        &lt;ul&gt;\n          {menu.map((item) =&gt; (\n            &lt;li key={item.href}&gt;\n              &lt;a href={item.href}&gt;{item.label}&lt;\/a&gt;\n            &lt;\/li&gt;\n          ))}\n        &lt;\/ul&gt;\n      &lt;\/nav&gt;\n      &lt;main&gt;{children}&lt;\/main&gt;\n    &lt;\/div&gt;\n  );\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Menus are fetched only once (or according to <code>revalidate<\/code>), so that the layout does not make unnecessary queries with each page.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Server components with cache &#8211; such as widgets or hero<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Often you have components that appear on many pages and don&#8217;t change very often &#8211; for example, a banner with a promotion, a weather widget, a &#8220;recommended articles&#8221; block.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Example:<\/h4>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ components\/HeroBanner.tsx\n'use cache';\n\nimport { getPromoBanner } from '@\/lib\/getPromoBanner';\n\nexport default async function HeroBanner() {\n  const banner = await getPromoBanner();\n\n  return (\n    &lt;section className=\"hero\"&gt;\n      &lt;h1&gt;{banner.title}&lt;\/h1&gt;\n      &lt;p&gt;{banner.subtitle}&lt;\/p&gt;\n    &lt;\/section&gt;\n  );\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In this way, the component manages its own cache &#8211; and can be used in multiple places without duplicating logic.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Asynchronous functions with cache &#8211; logic separated from the view<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to separate the data layer from the presentation layer, it&#8217;s a good idea to cache helper functions<code>(data loaders<\/code>) that only return data &#8211; and components only render them.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Example:<\/h4>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ lib\/getRecommendedPosts.ts\n'use cache';\n\nexport async function getRecommendedPosts(category: string) {\n  const res = await fetch(`https:\/\/api.example.com\/posts?category=${category}`, {\n    next: { revalidate: 300 },\n    \/\/ optional: tags: &#91;'recommended'],\n  });\n  return res.json();\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And usage:<\/p>\n\n\n\n<pre class=\"wp-block-code language-markup\"><code>\/\/ components\/RecommendedSection.tsx\nimport { getRecommendedPosts } from '@\/lib\/getRecommendedPosts';\n\nexport default async function RecommendedSection({ category }: { category: string }) {\n  const posts = await getRecommendedPosts(category);\n\n  return (\n    &lt;aside&gt;\n      &lt;h2&gt;Recomended articles&lt;\/h2&gt;\n      &lt;ul&gt;\n        {posts.map((p) =&gt; (\n          &lt;li key={p.id}&gt;{p.title}&lt;\/li&gt;\n        ))}\n      &lt;\/ul&gt;\n    &lt;\/aside&gt;\n  );\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This way, the component doesn&#8217;t need to know anything about the cache &#8211; that&#8217;s the job of <code>getRecommendedPosts<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Challenges and best practices \u2013 how to avoid the pitfalls of caching<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In the previous parts, we showed you how to implement caching in Next.js 15 step by step. Now it&#8217;s time for a practical look: what can go wrong, where typical mistakes lurk, and how to approach caching in a conscious, predictable, and scalable way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next.js 15 is extremely powerful, but like any advanced feature, it requires understanding and discipline. Below you will find a short list of the most common problems and best practices that will help you build fast, stable, and well-managed applications.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Common problems and errors<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>fetch<\/code>&nbsp;is not cached despite&nbsp;<code>'use cache'<\/code>&nbsp;\u2013 because dynamic functions (<code>headers()<\/code>,&nbsp;<code>cookies()<\/code>) are used.<\/li>\n\n\n\n<li>unaware overwriting of the cache \u2013 due to lack of&nbsp;<code>revalidate<\/code>&nbsp;or incorrect tags.<\/li>\n\n\n\n<li>data is cached for too long \u2013 lack of automatic refresh.<\/li>\n\n\n\n<li>failure to invalidate the cache after data editing \u2013 e.g. via the admin panel.<\/li>\n\n\n\n<li>attempting to cache the client component (<code>'use client'<\/code>) \u2013 which does not work.<\/li>\n\n\n\n<li>excessive caching of functions \u2013 which leads to unnecessary complication of logic.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Best practices<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>start by caching data, not components \u2013 first&nbsp;<code>fetch it<\/code>, then layout.<\/li>\n\n\n\n<li>use&nbsp;<code>revalidate<\/code>&nbsp;for variable data, e.g. every 60\u2013300 seconds.<\/li>\n\n\n\n<li>tag data (<code>cacheTag<\/code>) if you want to be able to invalidate a specific group.<\/li>\n\n\n\n<li>cache only what is really worth it &#8211; not everything needs to be stored.<\/li>\n\n\n\n<li>separate logic from rendering &#8211; a component should only display data, not decide on its freshness.<\/li>\n\n\n\n<li>create separate functions for dynamic and static data &#8211; don&#8217;t mix approaches.<\/li>\n\n\n\n<li>document caching decisions \u2013 it is easier to maintain in a team.<\/li>\n\n\n\n<li>test cache behavior with development build (<code>next dev<\/code>) and production build (<code>next build &amp;&amp; start<\/code>) \u2013 they may differ!<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Cache in Next.js 15 is not only an optimization tool, but a new way of thinking about application structure. By abandoning automatic caching and introducing mechanisms such as&nbsp;<code>'use cache'<\/code>,&nbsp;<code>revalidate<\/code>,&nbsp;<code>cacheTag<\/code>&nbsp;or&nbsp;<code>dynamicIO<\/code>, the programmer gains real control over the performance and up-to-dateness of data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this article, we show you how to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>work with the new caching model in Next.js 15,<\/li>\n\n\n\n<li>implement caching in functions, components and layouts,<\/li>\n\n\n\n<li>manage the data lifecycle and revalidation,<\/li>\n\n\n\n<li>avoid common mistakes and apply best practices.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The new system requires more awareness, but also provides more predictability and flexibility. This allows you to build an application that not only runs fast, but also provides users with up-to-date and reliable data &#8211; exactly when they need it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the world of JavaScript frameworks, Next.js has over the years built a reputation as a tool that combines the flexibility of React with server optimization capabilities. In version 15, Next.js developers made a breakthrough in their approach to caching &#8211; ditching the default aggressive caching in favor of more control on the developer side. This article is a guide to the new caching model in Next.js 15. You&#8217;ll learn how the new &#8216;use cache&#8217; directive works, what dynamicIO is, and how to practically use these features to make your applications not only faster, but also more predictable in performance.<\/p>\n","protected":false},"author":2,"featured_media":4858,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[17],"tags":[],"class_list":["post-3316","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-front-end"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Next.js 15 Caching - use cache, revalidate, dynamicIO and tags in practice<\/title>\n<meta name=\"description\" content=\"Learn how cache works in Next.js 15. A guide to &#039;use cache&#039;, revalidate, dynamicIO and cacheTag with practical examples, code structure and ready-to-use solutions.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Next.js 15 Caching - use cache, revalidate, dynamicIO and tags in practice\" \/>\n<meta property=\"og:description\" content=\"Learn how cache works in Next.js 15. A guide to &#039;use cache&#039;, revalidate, dynamicIO and cacheTag with practical examples, code structure and ready-to-use solutions.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/\" \/>\n<meta property=\"og:site_name\" content=\"Software House - rozwi\u0105zania IT dla Twojego biznesu | UniqueDevs\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/people\/Unique-Devs\/61564365418277\/\" \/>\n<meta property=\"article:published_time\" content=\"2025-04-09T12:57:13+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-11T07:43:46+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/uniquedevs.com\/wp-content\/uploads\/2025\/04\/programming-3652497_1280.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1280\" \/>\n\t<meta property=\"og:image:height\" content=\"908\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Hubert Olech\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Hubert Olech\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/\"},\"author\":{\"name\":\"Hubert Olech\",\"@id\":\"https:\/\/uniquedevs.com\/#\/schema\/person\/a2c9b776ac544a910615b03c8b9c4c18\"},\"headline\":\"How does caching work in Next.js 15? A practical introduction with examples\",\"datePublished\":\"2025-04-09T12:57:13+00:00\",\"dateModified\":\"2025-04-11T07:43:46+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/\"},\"wordCount\":1906,\"publisher\":{\"@id\":\"https:\/\/uniquedevs.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/uniquedevs.com\/wp-content\/uploads\/2025\/04\/programming-3652497_1280.webp\",\"articleSection\":[\"Front-end\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/\",\"url\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/\",\"name\":\"Next.js 15 Caching - use cache, revalidate, dynamicIO and tags in practice\",\"isPartOf\":{\"@id\":\"https:\/\/uniquedevs.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/uniquedevs.com\/wp-content\/uploads\/2025\/04\/programming-3652497_1280.webp\",\"datePublished\":\"2025-04-09T12:57:13+00:00\",\"dateModified\":\"2025-04-11T07:43:46+00:00\",\"description\":\"Learn how cache works in Next.js 15. A guide to 'use cache', revalidate, dynamicIO and cacheTag with practical examples, code structure and ready-to-use solutions.\",\"breadcrumb\":{\"@id\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#primaryimage\",\"url\":\"https:\/\/uniquedevs.com\/wp-content\/uploads\/2025\/04\/programming-3652497_1280.webp\",\"contentUrl\":\"https:\/\/uniquedevs.com\/wp-content\/uploads\/2025\/04\/programming-3652497_1280.webp\",\"width\":1280,\"height\":908},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Strona g\u0142\u00f3wna\",\"item\":\"https:\/\/uniquedevs.com\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Front-end\",\"item\":\"https:\/\/uniquedevs.com\/blog\/category\/front-end\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"How does caching work in Next.js 15? A practical introduction with examples\"}]},{\"@type\":\"Website\",\"@id\":\"https:\/\/uniquedevs.com\/#website\",\"url\":\"https:\/\/uniquedevs.com\/\",\"name\":\"Software House - rozwi\u0105zania IT dla Twojego biznesu | UniqueDevs\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/uniquedevs.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/uniquedevs.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},[],{\"@type\":\"Person\",\"@id\":\"https:\/\/uniquedevs.com\/#\/schema\/person\/a2c9b776ac544a910615b03c8b9c4c18\",\"name\":\"Hubert Olech\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/uniquedevs.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/uniquedevs.com\/wp-content\/litespeed\/avatar\/4aa41b6b162ba5c7c2dc5577af43de87.jpg?ver=1786517245\",\"contentUrl\":\"https:\/\/uniquedevs.com\/wp-content\/litespeed\/avatar\/4aa41b6b162ba5c7c2dc5577af43de87.jpg?ver=1786517245\",\"caption\":\"Hubert Olech\"},\"description\":\"Huber Olech - Founder @UniqueDevs. \u0141\u0105cz\u0119 \u015bwiat technologii z biznesem, pomagaj\u0105c firmom rozwija\u0107 si\u0119 dzi\u0119ki innowacyjnym rozwi\u0105zaniom cyfrowym. Pasja do software development zainspirowa\u0142a mnie do zbudowania zespo\u0142u ekspert\u00f3w, z kt\u00f3rymi wsp\u00f3lnie dostarczamy najwy\u017cszej jako\u015bci produkty dla swoich Klient\u00f3w. W oparciu o swoje wieloletnie do\u015bwiadczenie w bran\u017cy IT, rozumiem trendy w nowych technologiach i potrafi\u0119 przeku\u0107 je w wymierne korzy\u015bci dla firm. Moj\u0105 misj\u0105 jest tworzenie rozwi\u0105za\u0144, kt\u00f3re nie tylko usprawniaj\u0105 procesy, ale tak\u017ce otwieraj\u0105 przed Klientami nowe mo\u017cliwo\u015bci rynkowe i zwi\u0119kszaj\u0105 ich konkurencyjno\u015b\u0107.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/hubert-olech-b0a524167\/\"],\"url\":\"https:\/\/uniquedevs.com\/en\/blog\/author\/h-olech\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Next.js 15 Caching - use cache, revalidate, dynamicIO and tags in practice","description":"Learn how cache works in Next.js 15. A guide to 'use cache', revalidate, dynamicIO and cacheTag with practical examples, code structure and ready-to-use solutions.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"og_locale":"en_US","og_type":"article","og_title":"Next.js 15 Caching - use cache, revalidate, dynamicIO and tags in practice","og_description":"Learn how cache works in Next.js 15. A guide to 'use cache', revalidate, dynamicIO and cacheTag with practical examples, code structure and ready-to-use solutions.","og_url":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/","og_site_name":"Software House - rozwi\u0105zania IT dla Twojego biznesu | UniqueDevs","article_publisher":"https:\/\/www.facebook.com\/people\/Unique-Devs\/61564365418277\/","article_published_time":"2025-04-09T12:57:13+00:00","article_modified_time":"2025-04-11T07:43:46+00:00","og_image":[{"width":1280,"height":908,"url":"https:\/\/uniquedevs.com\/wp-content\/uploads\/2025\/04\/programming-3652497_1280.webp","type":"image\/webp"}],"author":"Hubert Olech","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Hubert Olech","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#article","isPartOf":{"@id":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/"},"author":{"name":"Hubert Olech","@id":"https:\/\/uniquedevs.com\/#\/schema\/person\/a2c9b776ac544a910615b03c8b9c4c18"},"headline":"How does caching work in Next.js 15? A practical introduction with examples","datePublished":"2025-04-09T12:57:13+00:00","dateModified":"2025-04-11T07:43:46+00:00","mainEntityOfPage":{"@id":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/"},"wordCount":1906,"publisher":{"@id":"https:\/\/uniquedevs.com\/#organization"},"image":{"@id":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#primaryimage"},"thumbnailUrl":"https:\/\/uniquedevs.com\/wp-content\/uploads\/2025\/04\/programming-3652497_1280.webp","articleSection":["Front-end"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/","url":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/","name":"Next.js 15 Caching - use cache, revalidate, dynamicIO and tags in practice","isPartOf":{"@id":"https:\/\/uniquedevs.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#primaryimage"},"image":{"@id":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#primaryimage"},"thumbnailUrl":"https:\/\/uniquedevs.com\/wp-content\/uploads\/2025\/04\/programming-3652497_1280.webp","datePublished":"2025-04-09T12:57:13+00:00","dateModified":"2025-04-11T07:43:46+00:00","description":"Learn how cache works in Next.js 15. A guide to 'use cache', revalidate, dynamicIO and cacheTag with practical examples, code structure and ready-to-use solutions.","breadcrumb":{"@id":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#primaryimage","url":"https:\/\/uniquedevs.com\/wp-content\/uploads\/2025\/04\/programming-3652497_1280.webp","contentUrl":"https:\/\/uniquedevs.com\/wp-content\/uploads\/2025\/04\/programming-3652497_1280.webp","width":1280,"height":908},{"@type":"BreadcrumbList","@id":"https:\/\/uniquedevs.com\/en\/blog\/how-does-caching-work-in-next-js-15\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Strona g\u0142\u00f3wna","item":"https:\/\/uniquedevs.com\/en\/"},{"@type":"ListItem","position":2,"name":"Front-end","item":"https:\/\/uniquedevs.com\/blog\/category\/front-end\/"},{"@type":"ListItem","position":3,"name":"How does caching work in Next.js 15? A practical introduction with examples"}]},{"@type":"Website","@id":"https:\/\/uniquedevs.com\/#website","url":"https:\/\/uniquedevs.com\/","name":"Software House - rozwi\u0105zania IT dla Twojego biznesu | UniqueDevs","description":"","publisher":{"@id":"https:\/\/uniquedevs.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/uniquedevs.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},[],{"@type":"Person","@id":"https:\/\/uniquedevs.com\/#\/schema\/person\/a2c9b776ac544a910615b03c8b9c4c18","name":"Hubert Olech","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/uniquedevs.com\/#\/schema\/person\/image\/","url":"https:\/\/uniquedevs.com\/wp-content\/litespeed\/avatar\/4aa41b6b162ba5c7c2dc5577af43de87.jpg?ver=1786517245","contentUrl":"https:\/\/uniquedevs.com\/wp-content\/litespeed\/avatar\/4aa41b6b162ba5c7c2dc5577af43de87.jpg?ver=1786517245","caption":"Hubert Olech"},"description":"Huber Olech - Founder @UniqueDevs. \u0141\u0105cz\u0119 \u015bwiat technologii z biznesem, pomagaj\u0105c firmom rozwija\u0107 si\u0119 dzi\u0119ki innowacyjnym rozwi\u0105zaniom cyfrowym. Pasja do software development zainspirowa\u0142a mnie do zbudowania zespo\u0142u ekspert\u00f3w, z kt\u00f3rymi wsp\u00f3lnie dostarczamy najwy\u017cszej jako\u015bci produkty dla swoich Klient\u00f3w. W oparciu o swoje wieloletnie do\u015bwiadczenie w bran\u017cy IT, rozumiem trendy w nowych technologiach i potrafi\u0119 przeku\u0107 je w wymierne korzy\u015bci dla firm. Moj\u0105 misj\u0105 jest tworzenie rozwi\u0105za\u0144, kt\u00f3re nie tylko usprawniaj\u0105 procesy, ale tak\u017ce otwieraj\u0105 przed Klientami nowe mo\u017cliwo\u015bci rynkowe i zwi\u0119kszaj\u0105 ich konkurencyjno\u015b\u0107.","sameAs":["https:\/\/www.linkedin.com\/in\/hubert-olech-b0a524167\/"],"url":"https:\/\/uniquedevs.com\/en\/blog\/author\/h-olech\/"}]}},"_links":{"self":[{"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/posts\/3316","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/comments?post=3316"}],"version-history":[{"count":4,"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/posts\/3316\/revisions"}],"predecessor-version":[{"id":3324,"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/posts\/3316\/revisions\/3324"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/media\/4858"}],"wp:attachment":[{"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/media?parent=3316"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/categories?post=3316"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/uniquedevs.com\/en\/wp-json\/wp\/v2\/tags?post=3316"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}