Problema
Equipes escolhem “SSR porque é moderno” ou “SSG porque é rápido” sem amarrar à frescor dos dados, personalização e carga no origin. Isso gera páginas lentas, builds enormes ou conteúdo desatualizado.
Solução
Decidir por perfil de dado: público vs autenticado; estático vs mutável; tolerância a staleness. Mapear cada rota a um modo (RSC com fetch dinâmico, generateStaticParams, revalidate, streaming) e documentar o SLA de frescor.
Arquitetura
| Cenário | Preferência típica |
|---|---|
| Marketing / docs | SSG + ISR |
| Catálogo com preços que mudam pouco | ISR (revalidate) |
| Dashboard autenticado | RSC + fetch dinâmico (sem cache agressivo) |
| Página altamente personalizada | SSR/RSC por request |
No App Router, “SSR vs SSG” muitas vezes vira cache de fetch + segment config (dynamic, revalidate).
Código
// Segmento estático com revalidação (ISR-like)
export const revalidate = 3600;
export default async function PricingPage() {
const res = await fetch("https://api.example.com/plans", {
next: { revalidate: 3600 },
});
const plans = await res.json();
return <PlanGrid plans={plans} />;
}// Dados sempre frescos para área logada
export const dynamic = "force-dynamic";
export default async function AccountPage() {
const session = await getSession();
return <Billing session={session} />;
}Performance
SSG/ISR melhoram TTFB e aproveitam CDN. SSR puro aumenta carga no servidor — compense com cache de borda (quando aplicável), queries enxutas e streaming de shell. Meça LCP e TTFB antes de “otimizar” à cegas.
Melhorias futuras
Stale-while-revalidate na camada de API; tags de invalidação (revalidateTag) para conteúdo editorial; observabilidade por rota (latência p95).
Conclusão
A pergunta certa não é “SSR ou SSG?” e sim “qual latência de dados o usuário e o negócio aceitam?”. Articular isso em code review é sinal de senioridade.