0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js 16のupdateTagとrevalidateTag、結局どう使い分ける?

0
Posted at

Next.jsのApp Routerでデータ更新後にキャッシュを無効化しようとすると、updateTag と revalidateTag のどちらを使うべきか迷いやすいです。

特にNext.js 16ではキャッシュAPIが整理され、updateTag() が追加される一方、revalidateTag() の推奨される使い方も変わりました。

この記事では、**「更新した本人にすぐ最新値を見せたいのか」「多少古い値を返してもレスポンスを優先したいのか」**という観点から使い分けを整理します。

この記事は2026年9月13日時点のNext.js公式ドキュメント(Next.js 16系)を確認して作成しています。

先に結論

大まかには次のように考えると分かりやすいです。

やりたいこと 選択肢
フォーム保存後、本人にすぐ最新値を見せたい updateTag()
ブログ・商品一覧など、少し古くても高速表示を優先したい revalidateTag(tag, 'max')
Route Handlerからタグを再検証したい revalidateTag()
Server Actionから即時反映したい updateTag()

最大の違いは、古いキャッシュを一時的に返してよいかです。

そもそもキャッシュタグとは

Next.jsではキャッシュしたデータに「タグ」という名前を付けられます。

例えば商品一覧に products というタグを付けておけば、商品更新時にそのタグだけを対象として再検証できます。

Next.js 16のCache Componentsを使う場合は、cacheTag() と 'use cache' を組み合わせられます。

import { cacheTag } from 'next/cache'

export async function getProducts() {
  'use cache'

  cacheTag('products')

  return db.product.findMany()
}

cacheTag() を利用するには、Cache Componentsを有効にします。

// next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  cacheComponents: true,
}

export default nextConfig

タグを付けておくことで、アプリ全体のキャッシュを消すのではなく、関連するデータだけを更新対象にできます。

updateTag:更新した本人にすぐ最新値を見せる

updateTag() はNext.js 16で追加されたAPIです。

特徴は、キャッシュを即座に期限切れにして、次の読み取りで古いキャッシュを返さず最新データを取得することです。

公式ドキュメントでは、これを read-your-own-writes のためのAPIとして説明しています。

read-your-own-writesとは、簡単に言えば、

自分が書き込んだデータを、その直後の読み取りで自分自身が確認できる

という性質です。

例えばプロフィール編集を考えます。

'use server'

import { updateTag } from 'next/cache'

export async function updateProfile(
  userId: string,
  name: string,
) {
  await db.user.update({
    where: { id: userId },
    data: { name },
  })

  updateTag(`user-${userId}`)
}

ユーザーが「田中」から「佐藤」に名前を変更した直後に、画面へ「田中」と表示されたら違和感があります。

このような操作結果をすぐ本人へ見せる必要がある処理では updateTag() が向いています。

注意:Server Actions限定

updateTag() はどこからでも呼べるわけではありません。

2026年9月時点の公式ドキュメントでは、Server Actionsからのみ利用可能です。

そのためRoute Handlerでは次のようには使えません。

// app/api/products/route.ts
// ❌ Route HandlerではupdateTagは使わない
import { updateTag } from 'next/cache'

外部サービスからWebhookを受け取るRoute Handlerなどでは、後述する revalidateTag() を使います。

revalidateTag:古い値を返しつつ裏で更新する

一方、revalidateTag() はServer FunctionsとRoute Handlersから利用できます。

Next.js 16では次の書き方が推奨されています。

import { revalidateTag } from 'next/cache'

revalidateTag('products', 'max')

'max' を指定すると、stale-while-revalidate(SWR) の動作になります。

SWRとは、

  1. まず手元にある古いキャッシュを返す
  2. 裏側で最新データを取得する
  3. 次回以降は新しいキャッシュを利用する

という考え方です。

つまり、利用者をデータ取得完了まで待たせるよりも、多少古い情報をすぐ表示することを優先します。

商品一覧ならrevalidateTagが使いやすい

例えばECサイトの商品一覧を考えます。

CMSから商品情報が更新されたタイミングでWebhookを受け取る場合、Route Handlerから再検証できます。

// app/api/webhooks/products/route.ts
import { revalidateTag } from 'next/cache'

export async function POST() {
  revalidateTag('products', 'max')

  return Response.json({ ok: true })
}

この場合、更新直後にアクセスした利用者へ一時的に古い商品一覧が表示されても許容できるなら、SWRとの相性が良いです。

また、revalidateTag('products', 'max') を呼んだ瞬間にすべての対象ページを再取得するわけではありません。

公式ドキュメントでは、タグを古い状態としてマークし、そのタグを利用するリソースへ次にアクセスが来たタイミングで再検証すると説明されています。

そのため、多数のページを一気に再生成する状況を避けやすくなります。

Next.js 15の記事を参考にするときは注意

ここはかなりハマりやすいポイントです。

以前は次の1引数形式をよく見かけました。

revalidateTag('products')

しかしNext.js 16では、この1引数形式は非推奨です。

現在は、SWRとして利用するなら次の形式が推奨されています。

revalidateTag('products', 'max')

また、Server Action内で「更新した直後から最新データを見せたい」のであれば、単純に昔の revalidateTag() の書き方をコピーするのではなく、updateTag() への置き換えを検討できます。

古いブログ記事やStack Overflowのコードをそのまま貼る場合は、対象のNext.jsバージョンを確認したほうが安全です。

実務ではどう判断するか

自分なら、まず次の質問をします。

1. 更新した本人が直後に見るデータか

YESなら updateTag() を検討します。

例:

  • プロフィール編集
  • 投稿作成
  • 設定変更
  • カート内容の変更

これらは「保存したのに画面が古い」という体験を避けたい処理です。

2. 少し古くても高速表示を優先できるか

YESなら revalidateTag(tag, 'max') が候補です。

例:

  • ブログ記事一覧
  • 商品カタログ
  • ドキュメント
  • ニュース一覧

3. Route Handlerから実行する必要があるか

YESなら revalidateTag() を使います。

updateTag() はServer Actions限定なので、Webhookなどからキャッシュを更新する場合には向きません。

よくある勘違い

updateTagはDBを更新するAPIではない

名前だけ見るとデータそのものを更新してくれそうですが、updateTag() が更新するのはキャッシュの状態です。

DBへの書き込みは自分で行います。

await db.product.update(...)

updateTag('products')

この2つは別の処理です。

revalidateTagを呼べば即座にバックグラウンド更新されるわけではない

revalidateTag(tag, 'max') は対象をstale(古い状態)として扱います。

最新データの取得は、そのタグを使うリソースへ次にアクセスされたタイミングで行われます。

タグ名は大文字・小文字を区別する

公式ドキュメントではタグはcase-sensitive、つまり大文字・小文字を区別するとされています。

cacheTag('products')

に対して、

updateTag('Products')

とすると同じタグとして扱われません。

また、タグ文字列は256文字以内という制限があります。

まとめ

updateTag() と revalidateTag() は、どちらが新しくて優れているという関係ではありません。

目的が違います。

更新した本人にすぐ最新値を見せたい
        ↓
     updateTag

多少古くてもまず高速に返したい
        ↓
 revalidateTag(tag, 'max')

特にNext.js 16では、revalidateTag(tag) の1引数形式が非推奨になっているため、過去の記事を参考にするときは注意が必要です。

キャッシュ設計では「キャッシュを消す方法」だけではなく、その画面では古い値を何秒・何リクエストまで許容できるのかを先に考えると、APIを選びやすくなります。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?