Capítulo 10 de 456

Revalidating

Core Idea

Revalidação atualiza dados cacheados mantendo respostas rápidas. Duas estratégias: baseada em tempo (cacheLife) e sob demanda (revalidateTag, updateTag, revalidatePath). Página cobre revalidação sob Cache Components.

Key Concepts

  • cacheLife: usada dentro de escopo use cache para controlar por quanto tempo o cache é válido; aceita nome de profile ou objeto customizado { stale, revalidate, expire }.
  • cacheTag: marca dados cacheados com uma tag para invalidação sob demanda; usada dentro de escopo use cache.
  • revalidateTag(tag, profile): invalida cache por tag com semântica stale-while-revalidate (conteúdo obsoleto é servido enquanto o novo carrega em background); usável em Server Actions e Route Handlers.
  • updateTag(tag): expira imediatamente o cache para cenários "read-your-own-writes"; usável somente em Server Actions.
  • revalidatePath(path): invalida todo o cache de uma rota específica sem depender de tags; usar quando não se sabe quais tags estão associadas à rota.
  • Cache "short-lived": cache que usa o profile seconds, revalidate: 0, ou expire abaixo de 5 minutos; é excluído automaticamente de prerenders e vira "dynamic hole".

Code Examples

import { cacheLife } from 'next/cache'

export async function getProducts() {
  'use cache'
  cacheLife('hours')
  return db.query('SELECT * FROM products')
}
  • O que demonstra: aplicar um profile de cache nomeado a uma função de dados.
'use cache'
cacheLife({
  stale: 3600, // 1 hora até considerado obsoleto
  revalidate: 7200, // 2 horas até revalidar
  expire: 86400, // 1 dia até expirar
})
  • O que demonstra: configuração customizada e granular de cacheLife.
import { revalidateTag } from 'next/cache'

export async function updateUser(id: string) {
  // Mutate data
  revalidateTag('user', 'max') // Recomendado: stale-while-revalidate
}
  • O que demonstra: invalidação sob demanda com stale window máximo, servindo conteúdo obsoleto até a atualização terminar.
import { updateTag } from 'next/cache'
import { redirect } from 'next/navigation'

export async function createPost(formData: FormData) {
  const post = await db.post.create({ data: { /* ... */ } })
  updateTag('posts')
  redirect(`/posts/${post.id}`)
}
  • O que demonstra: expirar imediatamente uma tag em Server Action para o usuário ver a própria escrita antes do redirect.

Reference Tables

Profilestalerevalidateexpire
default5m15mnever
seconds30s1s60s
minutes5m1m1h
hours5m1h1d
days5m1d1w
weeks5m1w30d
max5m30d1y
updateTagrevalidateTag
OndeSó Server ActionsServer Actions e Route Handlers
ComportamentoExpira cache imediatamenteStale-while-revalidate
Caso de usoRead-your-own-writesRefresh em background (atraso aceitável)

Anti-patterns

  • Usar revalidatePath quando tags bastam: menos preciso, invalida em excesso; preferir revalidateTag/updateTag.
  • Depender só de revalidação por tempo para conteúdo de CMS: gera revalidações desnecessárias; combinar cacheTag + cacheLife('max') com webhook do CMS chamando revalidateTag na mudança real.

Key Takeaways

  1. revalidateTag é stale-while-revalidate (rápido, leve atraso aceitável); updateTag expira na hora mas só funciona em Server Actions.
  2. Reaproveite a mesma tag em múltiplas funções para revalidar tudo de uma vez com uma chamada.
  3. Prefira tag-based revalidation a revalidatePath sempre que souber a tag: é mais preciso.
  4. Em ambientes serverless, entradas de cache em memória podem não persistir entre revalidações.
  5. Cache "não depende de dado de runtime" é o critério para decidir o que cachear com use cache + cacheLife.

Connects To

  • Caching (ch009): define use cache, cacheLife, cacheTag e o modelo de prerender que a revalidação aqui atualiza.