Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
YouTube Security VideosVisual Studio Code: VS Code Learn: Extending Agents(24.09.2026 um 21:00 Uhr)
•
YouTube Security VideosGoogle Cloud Tech: Turn Audio into Action with Gemini 3.5 Transcribe(24.09.2026 um 21:00 Uhr)
••••
Unix & Linux ServerUSN-8815-1: libass vulnerabilities(24.09.2026 um 16:57 Uhr)
•••••
YouTube Security VideosVisual Studio Code: VS Code Learn: Extending Agents(24.09.2026 um 21:00 Uhr)
•
YouTube Security VideosGoogle Cloud Tech: Turn Audio into Action with Gemini 3.5 Transcribe(24.09.2026 um 21:00 Uhr)
••••
Unix & Linux ServerUSN-8815-1: libass vulnerabilities(24.09.2026 um 16:57 Uhr)
•••••
Intelligence View
⚡ tsecurity.de Intelligence

On demand revalidation in Nextjs

Revalidation is about updating stale cache. Three functions can trigger revalidation on demand: revalidatePath revalidateTag updateTag These only work server-side: In a route handler (route.ts): e.g. called by a CMS webhook. In a…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Revalidation is about updating stale cache. Three functions can trigger revalidation on demand:




  1. revalidatePath

  2. revalidateTag

  3. updateTag



These only work server-side:




  • In a route handler (route.ts): e.g. called by a CMS webhook.

  • In a server action: after a user event like a form submit or clicking a refresh button.






RevalidatePath



revalidatePath invalidates cached data for a specific path. It targets data cache and full route cache if present.



The path can be




  • a specific url revalidatePath('/blog/a')

  • a route handler (route.ts)

  • a route pattern: revalidatePath('/blog/[postSlug]', 'page').



Note the second parameter type ('layout' | 'page'). When revalidating a route pattern, the second parameter is required.



This type parameter changes what is revalidated. Imagine this route setup:




app
layout.tsx
blog
[postSlug]
page.tsx






When calling revalidatePath('/blog/a'), the root layout.tsx will not be revalidated. This is the same as calling revalidatePath('/blog/a', 'page'):




revalidatePath('/blog/a');
// same as
revalidatePath('/blog/a', 'page');






If content of layout.tsx also needs to be revalidated, use the type parameter 'layout':




revalidatePath('/blog/a', 'layout');






But beware, this will revalidate all paths that use layout.tsx, nested paths as well, f.e. /blog/author/[slug]/page.tsx.






Cache invalidation mechanisms



We covered the stale while revalidate invalidation mechanism earlier in the time based revalidation section. All time-based revalidation uses stale while revalidate. On demand revalidation like revalidatePath is different.



When called from within a route handler, revalidatePath revalidates using the stale while revalidate mechanism. However, when called from inside a server action, revalidatePath will revalidate using the read-your-own-writes mechanism.






read-your-own-writes



read-your-own-writes purges the cache and immediately updates it. This is best explained with an example. Imagine your app has an edit account page, where a user can update their username. This would look like this:




  • User edits their name and clicks the save button.

  • This calls a server action that:


    • updates the DB

    • triggers on demand revalidation








What does the user expect to see after a successful update? Obviously their new username, not the old one (stale data). And that is where read-your-own-writes comes into play. Here is how it works:




  1. The server action calls on demand revalidation.

  2. Affected data is purged from the data cache and the full route cache if needed.

  3. Fresh data is fetched and stored in the data cache. If needed a new full route cache is rendered.

  4. The server action responds (e.g. status) and the fresh data and rendered route are sent along.



So, read-your-own-writes will immediately update the cache, whereas stale while revalidate does not. Server actions are called by user events (form submit, button click). Following this event, the user expects a change in the UI, this is critical.



There is a downside to read-your-own-writes. Updating the DB + revalidating the cache takes some time: the user has to wait. How do you handle this delay? Either a loading state or the useOptimistic hook. stale while revalidate does not suffer from this delay. It immediately returns data, stale data, but still, no wait.



Ok, now that we know about read-your-own-writes, let's return to revalidatePath. When it's called from:




  • Route handler -> stale while revalidate

  • Server action -> read-your-own-writes






stale while revalidate



Why is it fine to have stale while revalidate with route handlers? Let's explain by example:




  • You make a typo in a blog post.

  • You fix it in your headless CMS and save.

  • This triggers a webhook that calls an api endpoint in your app.

  • In this route handler you call revalidatePath for the relevant blog post path (e.g. /blog/post-a).



In this flow, there is no link between the event (happens in the CMS, not the app) and the UI of your app. The first user to visit /blog/post-a will still see the stale data (blogpost with typo). In the background, Next will refetch and rerender and serve the updated content to the next user. This is fine, it's not critical.



Of course, some things are critical - like a typo in a product price. You want that updated ASAP. But, this would require a different caching strategy. For a blog post, it's fine. I hope this makes sense, it all depends on the context.






More limitations



revalidatePath revalidates everything in the path. So, when there are multiple fetches, they will all be revalidated. This might not be desirable. If not, use a different caching strategy.



There is another limitation the docs describe. Let's say we have this tagged fetch (we cover tags below, but you probably know about them already):




fetch(url, { next: { tags: ['product-a'] } });






And we use it in 2 places products/a and products/promos. These 2 routes are statically rendered, that is prerended HTML and rsc. We update products/a with revalidateTag. This will update the data cache (the fetch with tag 'product-a') and the full route cache: .next/server/app/products/a.html and .next/server/app/products/a.rsc.



However, the prerendered products/promos page will not be revalidated. The data cache got updated but the prerendered route will still contain stale data! And that's a problem you can't fix. This is a big limitation when using revalidateTag.






Testing



Note: the examples are available on github.






revalidatePath in route handler (swr)



To run this test, we need a path:




// app/revalidate/path/swr/page.tsx

import Post from '@/components/Post';

export default function Page() {
return (
<>
<Post postId={35} fetchOptions={{}} />
<Post postId={36} fetchOptions={{ next: { revalidate: 1800 } }} />
<Post postId={37} fetchOptions={{ cache: 'force-cache' }} />
</>
);
}






We reuse the <Post /> component that we used in earlier chapters. Note that we set cache and time based revalidation. This is to test if all the fetches get revalidated.



We are testing calling revalidatePath from a route handler. This route handler would get called from an external place, e.g. a CMS webhook. This is our route handler, where we call revalidatePath:




// app/revalidate/api/revalidatePath/route.ts
// mostly from example https://nextjs.org/docs/app/api-reference/functions/revalidatePath#route-handler

export async function GET(request: NextRequest) {
const path = request.nextUrl.searchParams.get('path');

if (path) {
revalidatePath(path);
return Response.json({ revalidated: true });
}

return Response.json({
revalidated: false,
message: 'Missing path to revalidate',
});
}






Note that we get the path to revalidate not from a request body but from a searchParam: localApiEndpoint?path=pathToRevalidate. If there's a path we revalidate the path and return a response, else error response.



We will hit this endpoint directly from our browser. So paste url localhost:3000/revalidate/api/revalidatePath?path=/revalidate/path/swr in our browser url bar, hit enter. This will return us some json:




{"revalidated":true}






Note: Initially, I had written a separate route with a button to call this endpoint but that gave serious problems. Our route to revalidate was getting prefetched and saved in the browser cache (later more) and all my tests were failing because of this. To solve this, we call the endpoint directly and I added prefetch false to all the links in our examples overview page (home).



And let's run some tests.




[action]
next build
next start
visit localhost:3000/revalidate/api/revalidatePath?path=/revalidate/path/swr
get revalidated response
visit /revalidate/path/swr (path we just revalidated)
refresh page

[Expect]
✅ pass: Fresh content: the timestamp for all posts to have updated






Note: we already did an in depth test for SWR in the previous chapter. From now on, we will only rely on the displayed times of the posts in the front-end; to simplify these tests, e.g.




[TIMESTAMP]   [ID]  [TITLE]
17:24:31 35. id nihil consequatur molestias animi provident






So, we proved that:




  • Calling revalidatePath from a route handlers revalidates SWR.

  • All the fetches in the route were updated, even though one was cached "force-cache" for infinity and another { revalidate: 1800 }. Calling revalidatePath invalidated them both.



So, everything went as expected, great.



One more test. We have our route /revalidate/path/swr with 3 posts: 35-37. We make a copy of this route with the same 3 posts: /revalidate/path/swr-copy. The goal is to test if this route copy gets revalidated when we revalidate the original route.



We talked about this earlier. revalidatePath will update the data cache for these posts and the full route cache for this path. Our copy should therefore not get revalidated ... because the full route cache for this route copy will not be revalidated. We test it:




// app/revalidate/path/swr-copy/page.tsx

export default function Page() {
return (
<>
<Post postId={35} fetchOptions={{}} />
<Post postId={36} fetchOptions={{ next: { revalidate: 1800 } }} />
<Post postId={37} fetchOptions={{ cache: 'force-cache' }} />
</>
);
}









[action]
we continue after steps in prev example
visit /revalidate/path/swr-copy
refresh page

[Expect]
✅ pass: The timestamps did not update






I hope this is clear. Note, a dynamic route copy would update because there would be no full route cache for that route.






revalidatePath in a server action (read your own writes)



We make a new route:




// app/revalidate/path/ryow/page.tsx

export default function Page() {
return (
<>
<div className='mb-8'>
<Post postId={38} fetchOptions={{}} />
<Post postId={39} fetchOptions={{ next: { revalidate: 1800 } }} />
<Post postId={40} fetchOptions={{ cache: 'force-cache' }} />
</div>
<RevalidatePathActionButton routeToRevalidate='/revalidate/path/ryow' />
</>
);
}






We're using a server action now. No need to simulate an external webhook call. This is the button:




// components/revalidate/RevalidatePathActionButton.tsx
'use client';

import { revalidatePathAction } from '@/app/revalidate/_actions/revalidatePathAction';
import { useActionState, useTransition } from 'react';

export default function RevalidatePathActionButton({
routeToRevalidate,
}: {
routeToRevalidate: string;
}) {
const [state, dispatch] = useActionState(revalidatePathAction, null);
const [isPending, startTransition] = useTransition();

return (
<div className='my-5 flex gap-4 items-center'>
<button
onClick={() => {
startTransition(() => dispatch(routeToRevalidate));
}}
className='px-4 py-2 bg-blue-600 text-white rounded'
disabled={isPending}
>
Revalidat{isPending ? 'ing' : 'e'}
</button>

{state && state.revalidated && (
<p className='text-green-600 text-sm'>Revalidated</p>
)}

{state && !state.revalidated && (
<p className='text-red-600 text-sm'>
{state?.message || 'An error occurred while revalidating.'}
</p>
)}
</div>
);
}






Note that we use useActionState. We call the dispatch function directly from a button and therefore also need useTransition. The rest of the component is just a button and some status text.



Finally, this is our server action:




// app/revalidate/_actions/revalidatePathAction.ts

'use server';

type RevalidateStateT = {
revalidated: boolean;
message?: string;
} | null;

import { revalidatePath } from 'next/cache';

export async function revalidatePathAction(
_prevState: RevalidateStateT,
path: string,
) {
if (path) {
revalidatePath(path);
return {
revalidated: true,
};
}
return {
revalidated: false,
message: 'Missing path to revalidate',
};
}






When there is a path, revalidate it. Note that we need previous state because we call this action inside useActionState.



Great, we build and run it and here's read your own writes in action:



revalidatePath in action



No need to write expects here, we see that it works. The 3 posts update with a small delay. We confirm read your own writes when using revalidatePath from a server action.



Where does the updated data come from? That is just some rsc payload files being sent over.



We also make a route copy without a button, to see what happens.




// app/revalidate/path/ryow-copy/page.tsx

import Post from '@/components/Post';

export default function Page() {
return (
<>
<Post postId={38} fetchOptions={{}} />
<Post postId={39} fetchOptions={{ next: { revalidate: 1800 } }} />
<Post postId={40} fetchOptions={{ cache: 'force-cache' }} />
</>
);
}






Same as before, the copied route did not update, as expected.






Conclusion



revalidatePath is an easy revalidation solution for pages. There are limited ways to call it:




// specific url
revalidatePath('/blog/a');
// same as
revalidatePath('/blog/a', 'page'); // 'page' optional
// route pattern
revalidatePath('/blog/[postSlug]', 'layout'); // type parameter required: page | layout
// route handler
revalidatePath('/api/revalidate');






revalidatePath behaves differently depending on the context:




  • Route handler -> stale while revalidate

  • Server action -> read-your-own-writes



The upsides to revalidatePath are that it is quite easy to use. The downsides are:




  • It revalidates all fetches which can be undesirable.

  • It will not revalidate other routes that depend on the same revalidated data cache entries.



So, use it with care and probably avoid it in more complex situations.



Let's also take a step back here, to get a good overview. Since we're revalidating, there's a data cache. The page can be dynamic or static. If it's static then there will be a full route cache. Calling revalidatePath will revalidate the data cache and the full route cache (for that path). In a dynamic path, only the data cache will be revalidated.



Note: there is a nuclear option using revalidatePath: revalidatePath('/', 'layout'). This will revalidate everything. If you're using it, you're probably doing something wrong.



If you want to support my writing, you can donate with paypal.

CTI Threat Relationship Graph3 Knoten / 2 Relationen
CVE / Incident Software MITRE ATT&CK CWE Weakness IoC
SOC Incident Playbook: Remote Code Execution (RCE) Defense
Syntax validiert (0 Fehler)
title: Detect Exploitation - On demand revalidation in Nextjs
id: 30cfca00-1e8d-469f-a94a-c1dd824f5445
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-24
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
Syntax validiert (0 Fehler)
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-24"
        description = "YARA Signature for "
    strings:
        $str = "On demand revalidation in Next" ascii wide
    condition:
        any of them
}
Syntax validiert (0 Fehler)
index=security sourcetype IN ("cisco:asa", "pan:traffic", "zeek_conn", "suricata", "WinEventLog:Security")
("On demand revalidation in Nextjs")
| stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip, dest_ip, dest_host, signature
| eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S"), last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")
| sort - count
Syntax validiert (0 Fehler)
message: "*On demand revalidation in Nextjs*"
Syntax validiert (0 Fehler)
CommonSecurityLog
| where Message has "On demand revalidation in Nextjs"
| summarize EventCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, DestinationIP, DestinationPort, Activity
| extend DetectionRule = "iShareStuff-CTI-Compiled"
| sort by EventCount desc
🎯
MITRE ATT&CK Matrix Navigator 14 Taktiken
Reconnaissance
-
Resource Development
-
Initial Access
Execution
Persistence
-
Privilege Escalation
Defense Evasion
Credential Access
-
Discovery
-
Lateral Movement
-
Collection
-
Command and Control
Exfiltration
-
Impact
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich On demand revalidation in Nextjs.... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten On demand revalidation in Nextjs

Thematisch verwandte Begriffe: demand, revalidation, Nextjs · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-61782 | Rsdoctor is a build analyzer tailored for projects built with Rspack. Pr…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel • Rechts: nächster Artikel • unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel TTP ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...
↗ Original-Quelle