nextjs - 💡(How to fix) Fix revalidateTag with `expire: 0` not triggering immediate UI update when called from API route [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#86806Fetched 2026-04-08 02:09:03
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Author
Timeline (top)
closed ×1commented ×1labeled ×1locked ×1

Code Example

"use server";
import { cacheTag } from "next/cache";

export async function getCachedValue() {
  "use cache";
  cacheTag("random");
  return Math.random();
}

---

"use server";
import { revalidateTag } from "next/cache";

export async function invalidateCache() {
  revalidateTag("random", { expire: 0 });
}

---

import { revalidateTag } from "next/cache";

export async function GET() {
  revalidateTag("random", { expire: 0 });
  return Response.json({ revalidated: true });
}
RAW_BUFFERClick to expand / collapse

Version

Operating System: Platform: win32 Arch: x64 Version: Windows 10 Pro Available memory (MB): 32694 Available CPU cores: 24 Binaries: Node: 22.19.0 npm: 10.9.2 Yarn: 4.7.0 pnpm: N/A Relevant Packages: next: 16.0.7 // Latest available version is detected (16.0.7). eslint-config-next: N/A react: 19.2.0 react-dom: 19.2.0 typescript: 5.9.3 Next.js Config: output: N/A

Describe the bug

When using revalidateTag() with { expire: 0 } from an API route, the cache invalidation works but the UI doesn't update immediately. A manual page refresh is required to see the new cached value. This differs from server actions, which trigger immediate UI updates.

Reproduction

Repository: https://github.com/rRakarare/Next-js-cache-purge-via-route

Cached server function:

"use server";
import { cacheTag } from "next/cache";

export async function getCachedValue() {
  "use cache";
  cacheTag("random");
  return Math.random();
}

Server action (immediate UI update ✅):

"use server";
import { revalidateTag } from "next/cache";

export async function invalidateCache() {
  revalidateTag("random", { expire: 0 });
}

API route (requires page refresh ❌):

import { revalidateTag } from "next/cache";

export async function GET() {
  revalidateTag("random", { expire: 0 });
  return Response.json({ revalidated: true });
}

Expected behavior

According to the documentation, { expire: 0 } should lead to immediate new values. When calling the API route, the page should automatically display the fresh cached value without requiring a manual refresh, matching the server action behavior.

Actual behavior

  • Server action: Page immediately shows new value after invalidation
  • API route: Cache is invalidated successfully, but page continues showing old value until manually refreshed

Question

How can I achieve the same immediate UI update behavior with API route calls as with server actions?

extent analysis

TL;DR

The issue can be resolved by using a server action instead of an API route to invalidate the cache, or by implementing a mechanism to refresh the page after the API route call.

Guidance

  • The revalidateTag function is working as expected in terms of cache invalidation, but the UI update is not triggered when called from an API route.
  • To achieve immediate UI updates, consider using a server action instead of an API route for cache invalidation, as shown in the provided example.
  • If using an API route is necessary, implement a mechanism to refresh the page after the cache invalidation, such as returning a redirect response or using client-side JavaScript to refresh the page.
  • Verify that the cache is being invalidated correctly by checking the cache status after the API route call.

Example

// API route with page refresh
import { revalidateTag } from "next/cache";

export async function GET() {
  revalidateTag("random", { expire: 0 });
  return Response.redirect(302, '/'); // Refresh the page
}

Notes

The provided example uses a simple redirect to refresh the page, but this may not be suitable for all use cases. A more sophisticated approach may be needed to handle different scenarios.

Recommendation

Apply workaround: Use a server action for cache invalidation or implement a page refresh mechanism after the API route call, as the current implementation of revalidateTag in API routes does not support immediate UI updates.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

According to the documentation, { expire: 0 } should lead to immediate new values. When calling the API route, the page should automatically display the fresh cached value without requiring a manual refresh, matching the server action behavior.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING