revalidateTag
Purge every cached page that carries a cache tag, from server code, so the next request for each renders fresh.
ts
import { revalidateTag } from '@gio.js/core';
await revalidateTag('posts');Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
tag (required) | string | - | A tag pages declared with export const tags = ['posts'] or returned from getServerSideProps as { props, tags: ['post:42'] }. |
Returns
A Promise<RevalidateResult>: { ok, purged, error? }, the same as revalidatePath. purged counts the cache entries removed - each query-string and locale variant of a page is one entry.
Behavior
- Every cached page stored under the tag is dropped from memory and disk, PPR shells included, and the promise resolves once the server confirms it. The next request for each of those pages renders fresh.
- A page is stored under the tags of the render that produced it: its
export const tagsplus thetagsitsgetServerSidePropsreturned for that render. - Unconfirmed purges resolve
{ ok: false, purged: 0, error }after 5 seconds (or when the server connection drops) and log a warning - they never throw. At most 16 calls are in flight per worker; the rest wait their turn.
Tag rules
The same rules apply to the tags pages declare. revalidateTag() rejects with a TypeError for a tag that breaks one; a page's invalid tags are dropped with a warning (logged once per route and problem) instead of failing the render.
- A non-empty string of at most 256 bytes (UTF-8).
- No control characters and no unpaired UTF-16 surrogates.
- Not starting with
_gio:- that prefix is the server's own (it tags every page with its path, forrevalidatePath). - A page keeps at most 64 tags; duplicates count once, and the rest are dropped with a warning.
Examples
Tag a list and its items
app/posts/[id]/page.tsx
import { notFound, type GetServerSideProps, type InferPageProps } from '@gio.js/core';
export const revalidate = 60;
export const tags = ['posts']; // every render of this page
export const getServerSideProps = (async (ctx) => {
const post = await db.posts.find(ctx.params.id);
if (post === null) notFound();
return { props: { post }, tags: [`post:${post.id}`] }; // this render only
}) satisfies GetServerSideProps<{ post: Post }, '/posts/:id'>;
export default function PostPage({ post }: InferPageProps<typeof getServerSideProps>) {
return <article><h1>{post.title}</h1></article>;
}app/api/posts/[id]/route.ts
import { notFound, revalidateTag, type GioRequest } from '@gio.js/core';
export async function PUT(req: GioRequest<'/api/posts/:id'>) {
const { title } = req.json<{ title: string }>();
const post = await db.posts.update(req.params.id, title);
if (post === null) notFound();
const result = await revalidateTag(`post:${post.id}`);
return { post, purged: result.purged };
}With /posts/1 cached, the PUT answers "purged": 1, and the next GET /posts/1 is a miss in X-Gio-Cache that shows the new title.
Purge a batch
ts
const results = await Promise.all(changedIds.map((id) => revalidateTag(`post:${id}`)));
const failed = results.filter((r) => !r.ok);Good to know
- Tags apply to cached pages only - pages with
revalidateset. A personalized render (one that read cookies, or sent its ownset-cookie) is never stored, so it carries no tags.renderPage()in tests shows the tags a render would be stored under incacheTags. - One server instance. Other instances need
POST /_gio/revalidatewith{ "tags": [...] }- see Caching. - Outside the server (
gio export, unit tests) it resolvesok: falseand warns once.
Related
- Caching: Tagging pages
- export const tags
- revalidatePath
- renderPage - assert a page's
cacheTags
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Introduced. |