Desenvolvimento & IA 6 min de leitura

“Na Minha Máquina Funciona”: O Bug de Cache na Vercel que Fez Perder um Cliente

Guilherme Nascimento 0 comentários

Poucas frases destroem tanto a reputação de um desenvolvedor quanto: “Aqui na minha máquina está funcionando perfeitamente, tenta dar um Ctrl+F5”.

O caso clássico que assombra agências e freelancers aconteceu em uma sexta-feira: uma alteração emergencial de tabela de preços e banners para uma campanha ao vivo. O desenvolvedor alterou o código, submeteu o commit, viu o check verde da Vercel (Deployment Ready in 32s) e abriu a página. Tudo lindo.

Ele avisou o cliente: “Tudo atualizado em produção!”. Dez minutos depois, veio a mensagem furiosa da diretoria com prints do celular e de computadores corporativos: os preços antigos continuavam lá. O cliente perdeu vendas, acusou a equipe de incompetência técnica e cancelou o contrato no mesmo dia.

Se você trabalha com Next.js e Vercel, este post-mortem é a sua vacina para nunca passar por esse pesadelo.

⚡ Anatomia do Desastre em 30 Segundos (TL;DR)

O que o Dev Viu O que o Cliente Viu Onde Estava o Vilão Real A Correção Imediata
Preços novos e layout 100% atualizado no navegador Preços antigos em cache com desconto incorreto **Vercel Edge Data Cache & Full Route Cache** estático `revalidatePath()` ou `export const dynamic = ‘force-dynamic’`

🔍 Onde Estava o Erro: A Falsa Ilusão da “Minha Máquina”

Por que a página atualizou instantaneamente para o programador, mas permaneceu estagnada por horas para o cliente e milhares de usuários?

A resposta está na confusão entre 3 ambientes completamente diferentes:

💻
Localhost

No Ambiente de Dev (next dev)

O servidor local reexecuta requisições a cada reload. Não existe Edge CDN nem camadas agressivas de Data Cache ativas. Tudo parece dinâmico e instantâneo.

🔗
Deployment URL

Na URL com Hash Única

O dev abriu o link gerado pelo deploy (ex: projeto-a1b2c3.vercel.app). Como essa URL nunca foi acessada por ninguém, ela gerou um cache virgem e limpo.

🚨
Produção

No Domínio Real do Cliente

O cliente acessou empresa.com.br. Os pontos de presença (PoPs) da CDN da Vercel entregaram a página estática pré-compilada, ignorando novos dados.

⚙️ As 4 Camadas Ocultas de Cache na Vercel e Next.js

Para não ser vítima desse erro, você precisa entender que a Vercel não tem apenas “um” cache, mas uma pilha de quatro níveis sobrepostos:

  1. Client Router Cache (Navegador): Armazena a estrutura da página na sessão do usuário. Mudar de aba e voltar não busca novos dados no servidor.
  2. Full Route Cache (Servidor): Páginas estáticas são geradas uma única vez no momento do build (next build) e congeladas no storage da Vercel.
  3. Next.js Data Cache (Requisições fetch): Por padrão, no Next.js App Router, chamadas fetch() guardam o resultado indefinidamente no disco do servidor a menos que você configure explicitamente o tempo de vida.
  4. Vercel Edge Network Cache (CDN Global): Réplicas da página distribuídas em centenas de servidores pelo mundo com cabeçalhos s-maxage e stale-while-revalidate.
⚠️Atenção Crítica

O Erro Fatal de Comunicação: Mandar um cliente leigo ou diretor de empresa “limpar o cache do navegador” quando o problema está no Edge Cache da Vercel queima instantaneamente a sua credibilidade técnica.

💻 O Código Culpado vs. O Código Seguro

Veja exatamente onde o código quebrou e como deveria ter sido escrito:

❌ O Código Ingênuo (Causador do Desastre)

typescript
// app/precos/page.tsx
// Sem diretivas, o Next.js trata essa rota como 100% estática!
export default async function PrecosPage() {
  const res = await fetch('https://api.empresa.com/produtos');
  const produtos = await res.json();

  return <TabelaPrecos itens={produtos} />;
}

O que aconteceu aqui: O Next.js fez o cache do JSON durante o build da Vercel. Não adiantou o cliente alterar os preços no banco de dados ou no painel: a página servia a resposta congelada.

✅ Solução 1: Quando a página PRECISA de dados em tempo real

Se a tabela de preços depende de dados vivos do banco, desative o cache na rota:

typescript
// app/precos/page.tsx
export const dynamic = 'force-dynamic'; // Força renderização dinâmica
export const revalidate = 0;           // Zero cache no servidor

export default async function PrecosPage() {
  const res = await fetch('https://api.empresa.com/produtos', {
    cache: 'no-store' // Ignora o Next.js Data Cache
  });
  const produtos = await res.json();

  return <TabelaPrecos itens={produtos} />;
}

✅ Solução 2: Revalidação Sob Demanda (A Melhor Prática)

Se você quer a velocidade de uma página estática (carregamento em 50ms), mas precisa atualizar no instante em que o cliente salva um produto no painel:

typescript
// app/api/revalidate/route.ts
import { revalidatePath, revalidateTag } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  const secret = request.headers.get('x-webhook-secret');
  
  // Valida a chave secreta enviada pelo painel administrativo
  if (secret !== process.env.ADMIN_WEBHOOK_SECRET) {
    return NextResponse.json({ message: 'Acesso negado' }, { status: 401 });
  }

  // Purga instantaneamente o cache da rota e do Edge da Vercel
  revalidatePath('/precos');
  
  return NextResponse.json({ revalidated: true, now: Date.now() });
}

🛡️ Checklist Anti-Demissão: Como Testar Antes de Falar com o Cliente

Antes de mandar mensagem para qualquer cliente dizendo que “está pronto”, faça este teste de 60 segundos no terminal:

  1. Inspecione os Cabeçalhos HTTP com o cURL:

Execute no terminal para ver a verdade nua e crua sobre o cache:
“bash
curl -I https://seusite.com.br/precos
`

  1. Observe o Header x-vercel-cache:

- HIT: A página veio do cache do servidor (pode estar velha se o dado mudou).
-
STALE: A Vercel está entregando o dado velho enquanto tenta revalidar em segundo plano.
-
MISS ou BYPASS: A página acabou de ser gerada do zero com os dados mais recentes.

  1. Force a Purga no Painel da Vercel em Caso de Crise:

Vá no dashboard do seu projeto na Vercel > Settings > Data Cache e clique em Purge Everything. Isso zera o cache de todos os PoPs da CDN mundial imediatamente.

  1. Teste pelo Celular no 4G (Fora do Wi-Fi):

O seu computador pode estar pegando rotas DNS e caches intermediários do roteador. Uma checagem de 10 segundos numa rede 4G limpa revela o que o cliente de fato está vendo.

💡 O Que Aprendemos com Essa Perda de Contrato

A perda daquele cliente foi dolorosa, mas ensinou uma lição essencial para qualquer desenvolvedor sênior:

  • Deploy não termina no git push: O deploy só acaba quando a validação do cabeçalho de resposta HTTP confirma que o Edge Node está servindo o conteúdo correto.
  • Transparência gera respeito: Se o cliente disser que não está vendo a alteração, não debata. Diga: "Vou verificar o status de propagação do cache da nossa rede agora mesmo" em vez de sugerir que o erro é do usuário.
💡Dica Prática

Dica do Especialista Hora Nerd: Em aplicações críticas de e-commerce e faturamento, use sempre tags de cache (next: { tags: [‘produtos’] }`) e integre a revalidação direta via Webhooks no seu CMS ou painel de controle.

Gostou deste post-mortem? Confira nossos outros guias sobre DevOps e confira nossos Cheatsheets para comandos rápidos de terminal e infraestrutura.

Guilherme Nascimento ✓

Guilherme Nascimento

Especialista & Fundador

Especialista em Infraestrutura, Cloud/DevOps e Cibersegurança | +10 anos de experiência prática

Profissional com mais de uma década atuando no campo de batalha da tecnologia corporativa. Especialista em arquiteturas resilientes, automação com Docker/Kubernetes, Hardening de Active Directory, Linux avançado e observabilidade SRE. Criador do ecossistema Hora Nerd, dedicado a desmistificar a tecnologia para profissionais e estudantes.

Cloud & DevOps Active Directory Hardening Linux SysAdmin Docker & CI/CD Observabilidade SRE

Deixe seu comentário

Seu e-mail não será publicado. Campos obrigatórios estão marcados com *