// app/api/revalidate/route.ts
import { revalidateTag } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest) {
const secret = req.headers.get('x-revalidate-secret');
if (secret !== process.env.CMS_WEBHOOK_SECRET) {
return NextResponse.json({ message: 'Unauthorized' }, { status: 401 });
}
const { tag } = await req.json();
if (!tag) {
return NextResponse.json({ message: 'Tag lipsă' }, { status: 400 });
}
// Invalidează instant doar paginile legate de tag-ul respectiv
revalidateTag(tag);
return NextResponse.json({ revalidated: true, now: Date.now() });
}Mulți pun export const revalidate = 60 peste tot în App Router și speră să fie bine. Am făcut și eu greșeala asta până când ne-am trezit într-un Black Friday cu prețuri desincronizate și baza de date sufocată de rebuild-uri în background. Alegerea între static, periodic și on-demand nu e teorie de documentație, ci ține direct de factura de hosting și de date corecte servite utilizatorilor.
Hai să trecem prin 5 cazuri reale pe care le-am întâlnit în producție și cum am rezolvat fiecare problemă.
1. Catalogul de produse (14k SKU-uri)
La un magazin online de piese auto, generarea complet statică (SSG cu generateStaticParams) dura 42 de minute la build time pe Vercel. Deseori pica la timeout.
Soluția pe care am mers: am generat la build doar primele 200 cele mai vizitate pagini, iar restul le-am lăsat pe fallback la cerere. Însă în loc de ISR pe timp (revalidate = 3600), am folosit On-Demand Revalidation prin tag-uri. Când ERP-ul actualizează un produs, trimite un webhook care cheamă revalidateTag('product-123'). Astfel, cache-ul stă neatins până când se schimbă ceva cu adevărat, iar build-ul a scăzut de la 42 de minute la sub 3 minute.
2. Blogul de conținut sau site-ul de prezentare
Aici SSG pur rămâne rege. Dacă publici un articol la 2 zile sau schimbi textul de pe pagina de Contact o dată pe lună, n-ai niciun motiv să bagi complexitate de tag-uri sau revalidare temporală.
Faci deploy la build, paginile sunt HTML chior pe CDN, zero interogări la baza de date în producție. Cel mai ieftin, cel mai rapid posibil.
3. Prețul și stocul volatil în e-commerce
Aici e capcana: mulți încearcă să facă ISR la 10 secunde. E o prostie. În alea 10 secunde, un utilizator poate cumpăra un produs la 100 de lei care tocmai s-a scumpit la 150.
Trade-off-ul pe care îl aplic: pagina e statică (ISR/SSG) pentru text, specificații și poze, dar blocul de preț și stoc e randat client-side sau adus printr-un Server Component dinamic (no-store). Static pentru SEO și TTFB impecabil, dinamic strict pentru datele critice.
4. Dashboard B2B / SaaS multi-tenant
Aici ISR și SSG sunt complet interzise. Dacă scapi accidental un cache la nivel de fetch pentru date financiare sau date specifice unui tenant, riști să servești datele firmei A către firma B. Pentru dashboard-uri mergi exclusiv pe Dynamic Rendering (SSR clasic fără cache pe fetch-uri de date private) sau SPA pur în spatele autentificării.
5. Ghidul rapid de decizie
Ca regulă generală:
- Conținutul se schimbă doar la deploy? -> SSG pur.
- Conținutul se schimbă din CMS/bază de date la intervale neregulate? -> On-Demand cu
revalidateTag. - Conținutul e public, are volum uriaș, dar nu ai webhook-uri din sursa de date? -> ISR cu timp generos (minim 10-30 minute).
- Datele sunt legate de sesiune sau utilizator autentificat? -> Dynamic (no-store).
Voi cum gestionați invalidarea de cache în App Router pe proiecte mari: ați trecut complet pe webhook-uri cu revalidateTag sau vă mai bazați pe revalidare la intervale fixe?