Skip to main content

Arquivo de Caso · INV-0053

Dez minutos de erros 500 durante um pico no LinkedIn — sem nenhum cache de fallback

Uma publicação no LinkedIn gerou um grande volume de novos visitantes para o site da SimUser AI. O CMS não suportou a carga e começou a retornar erros 503. Sem camada de cache e sem fallback, cada requisição virou um erro 500 — por dez minutos seguidos.

6 min de leituraAltaLeads perdidos durante o picoResolvido pelo CauseFlow em 5 min

A Arquitetura que Falhou

Cada requisição de página buscava o conteúdo diretamente no CMS em tempo real. Não havia cache entre a função Lambda e o CMS — tornando o CMS um ponto único de falha.

Visitantes
CDN
Next.js Lambda
CMS

sem fallback — toda requisição → 500

Tráfego vs. Erros 5xx

O volume de requisições e a taxa de erros subiram juntos. O CMS não aguentou o pico — cada novo visitante recebia um erro 500 em vez da página.

Requisições / minErros 5xx
Post no LinkedInCMS recuperadoTempo →
Lambda WebsiteServer — CloudWatch Logs
{"level":"error","msg":"CMS API request failed","endpoint":"https://cms.simuser.ai/api/pages/get-started","status":503,"elapsedMs":4200}
{"level":"warn","msg":"CMS unavailable — no fallback cache found for path","path":"/get-started"}
{"level":"error","msg":"Rendering error page","statusCode":500,"reason":"CMS_UNAVAILABLE","path":"/get-started"}

O Cache que Nunca Foi Aquecido

Um scan no DynamoDB confirmou a causa raiz: 80 registros de cache, todos com revalidatedAt: 1 — o sentinel de época Unix para "nunca revalidado desde o deploy".

DynamoDB · WebsiteRevalidationTable

80 registros
caminhorevalidatedAt
/get-started?v=0011
/pt-br/get-started?v=0021
/get-started?v=0031
/pt-br/get-started?v=0041
/get-started?v=0051
/pt-br/get-started?v=0061
/get-started?v=0071
/pt-br/get-started?v=0081
/get-started?v=0091
/pt-br/get-started?v=0101
/get-started?v=0111
/pt-br/get-started?v=0121
/get-started?v=0131
/pt-br/get-started?v=0141
/get-started?v=0151
/pt-br/get-started?v=0161
/get-started?v=0171
/pt-br/get-started?v=0181
/get-started?v=0191
/pt-br/get-started?v=0201
/get-started?v=0211
/pt-br/get-started?v=0221
/get-started?v=0231
/pt-br/get-started?v=0241
/get-started?v=0251
/pt-br/get-started?v=0261
/get-started?v=0271
/pt-br/get-started?v=0281
/get-started?v=0291
/pt-br/get-started?v=0301
/get-started?v=0311
/pt-br/get-started?v=0321
/get-started?v=0331
/pt-br/get-started?v=0341
/get-started?v=0351
/pt-br/get-started?v=0361
/get-started?v=0371
/pt-br/get-started?v=0381
/get-started?v=0391
/pt-br/get-started?v=0401
/get-started?v=0411
/pt-br/get-started?v=0421
/get-started?v=0431
/pt-br/get-started?v=0441
/get-started?v=0451
/pt-br/get-started?v=0461
/get-started?v=0471
/pt-br/get-started?v=0481
/get-started?v=0491
/pt-br/get-started?v=0501
/get-started?v=0511
/pt-br/get-started?v=0521
/get-started?v=0531
/pt-br/get-started?v=0541
/get-started?v=0551
/pt-br/get-started?v=0561
/get-started?v=0571
/pt-br/get-started?v=0581
/get-started?v=0591
/pt-br/get-started?v=0601
/get-started?v=0611
/pt-br/get-started?v=0621
/get-started?v=0631
/pt-br/get-started?v=0641
/get-started?v=0651
/pt-br/get-started?v=0661
/get-started?v=0671
/pt-br/get-started?v=0681
/get-started?v=0691
/pt-br/get-started?v=0701
/get-started?v=0711
/pt-br/get-started?v=0721
/get-started?v=0731
/pt-br/get-started?v=0741
/get-started?v=0751
/pt-br/get-started?v=0761
/get-started?v=0771
/pt-br/get-started?v=0781
/get-started?v=0791
/pt-br/get-started?v=0801

Descoberta Crítica

Todos os 80 registros de cache para a página afetada mostram revalidatedAt: 1 — o cache foi definido no deploy e nunca foi aquecido. Quando o CMS ficou indisponível, não havia nada para servir.

Antes e Depois: Estratégia de Cache

A correção foi estrutural — migrar de SSR a cada requisição para ISR com janela de revalidação de 5 minutos e fallback try/catch para o cache obsoleto.

Antes

SSR — busca a cada requisição, sem cache

LambdaSSRsem cacheCMS503ponto único de falha

Depois

ISR + fallback — cache obsoleto é melhor que erro 500

LambdaISRCache ISRrevalidate: 300fallback obsoleto

Impacto nos Negócios

Leads estimados perdidos

~40

Com base na taxa de conversão média e no volume de tráfego durante a janela de 10 minutos. Cada visitante que encontrou um erro 500 na página Get Started era um potencial cadastro de trial.

Estimativa: 400 visitantes × 10% de taxa de cadastro × 10 min de interrupção

Causa Raiz e Correção

A página usava SSR puro com uma busca síncrona ao CMS em cada requisição. A correção: migrar para ISR com revalidate: 300 e um fallback try/catch que serve conteúdo obsoleto em vez de lançar erro.

Antes — SSR: falha no CMS → erro 500typescript
// pages/get-started — SSR: fetch on every request
export default async function GetStartedPage() {
  const content = await fetch('https://cms.simuser.ai/api/pages/get-started')
    .then(r => r.json());
  // CMS 503 → this throws → Next renders 500 to the user
  return <PageContent data={content} />;
}
Depois — ISR + fallback: falha no CMS → cache obsoletotypescript
// ISR — cached for 5 min, tolerant to CMS outages
export const revalidate = 300; // 5 minutes

export default async function GetStartedPage() {
  const content = await fetchWithFallback();
  return <PageContent data={content} />;
}

async function fetchWithFallback() {
  try {
    const res = await fetch('https://cms.simuser.ai/api/pages/get-started', {
      next: { revalidate: 300 },
      signal: AbortSignal.timeout(3000),
    });
    if (!res.ok) throw new Error(`CMS returned ${res.status}`);
    return await res.json();
  } catch (err) {
    console.error({ msg: 'CMS fetch failed — serving stale cache', err });
    return null; // Next.js serves ISR cache automatically
  }
}

Pare de caçar a causa raiz sob pressão
— deixe o CauseFlow encontrar.

O CauseFlow correlaciona registros do DynamoDB, logs do Lambda e métricas do CloudWatch automaticamente — sem triagem manual de logs, sem arqueologia de post-mortem.