Skip to main content

Case File · INV-0051

Pricing page froze 25 minutes after a CMS update

A missing tag mapping and a silent TypeError combined to block every revalidation job — leaving SimUser AI's pricing page stuck on old data right before a 15% price repositioning went live.

5 min readHighStale pricing visible to leadsFixed by CauseFlow in 3 min

The Symptom

On April 16, 2026, Felipe Aguiar (Head of Marketing, SimUser AI) pushed a 15% price update across all plans via Contentful at 11:20 UTC. At 11:45 UTC a lead confirmed the /pricing page still showed the old numbers. The marketing team had already shared the updated pricing in an email blast — visitors clicking through saw stale data.

11:20 UTC — CMS publish11:45 UTC — first report

Evidence Board

DynamoDB · Revalidation Job
tag: "revalidate"
path: "/pricing"
status: "pending"
retries: 3
error: "TypeError: Cannot read properties
of undefined (reading NewImage)
at handler (/var/task/index.js:23:45)"
deployId: "deploy-20260416-030158"
deployVersion:"v2.4.0"
timestamp: "2026-04-16T03:02:14Z"
DynamoDB · Cache Entries (71 rows)
71 rows returned — all paths containing "/pricing"
tag: "{deployId}/_N_T_/[locale]/pricing/page"
path: "{deployId}/en/pricing"
revalidatedAt:"1" ← never revalidated since deploy
→ No cache invalidation reached any /pricing variant.
CloudWatch · Seeder Lambda
Log group: /aws/lambda/simuser-ai-production-
WebsiteRevalidationSeederFunction
{"level":"warn",
"msg":"Tag not found in revalidation table",
"tag":"pricing-page",
"pathCount":0,
"note":"No paths registered for this tag — skipping"}
Affected Routes
  • /
  • /pricing
  • /features
  • /blog/simuser-ai-v2-launch
  • /blog/…

Where the Pipeline Broke

Two overlapping bugs blocked every revalidation attempt. Hover each X to see the failing code.

CMSContentfulWebhookHTTP POSTSeederLambdaDynamoDBTableSubscriberLambdaNext.jsBug 1: Missing tag mapping"pricing-page" → no paths registeredSeeder skips — pathCount: 0Bug 2: TypeError at handler:23record.dynamodb.NewImage undefinedon DELETE events → retries: 3 → stuckworking pathblocked pathfailure point (hover for details)

Systemic Blast Radius

The TypeError in the Subscriber handler affected every route that had a queued revalidation job — not just /pricing. Any page touched by a DynamoDB Streams event during this window was silently stuck.

  • /
  • /pricing
  • /features
  • /blog/simuser-ai-v2-launch
  • /blog/…

Symptom → Root Cause

  1. 1

    Symptom: /pricing shows stale prices

    Lead reports old plan prices; CMS publish was 25 min ago.

  2. 2

    DynamoDB job stuck at retries: 3

    TypeError on NewImage blocks all revalidation jobs — any DELETE event crashes the handler.

  3. 3

    Seeder skips /pricing entirely

    Tag 'pricing-page' has no paths registered in the revalidation table; pathCount: 0.

  4. 4

    Root cause: two overlapping bugs

    Missing tag map + unguarded NewImage access = no revalidation ever reaches Next.js.

Root Cause & Fix

Bug 1 — Missing tag mapping

The CMS webhook sends the tag pricing-page, but no entry in the DynamoDB table maps that tag to the /pricing path. The Seeder logs a warn and exits without queuing any invalidation.

Bug 2 — Unguarded NewImage access

The RevalidationEventsSubscriber reads event.Records[i].dynamodb.NewImage unconditionally. DynamoDB Streams DELETE events omit NewImage, causing a TypeError that puts every affected job into an unrecoverable retries: 3 / status: pending state.

Before — handler crashes on DELETE eventsjavascript
// handler (/var/task/index.js:23)
const newImage = record.dynamodb.NewImage; // crashes on DELETE events
await revalidatePath(newImage.path.S);
After — guarded handlerjavascript
// handler (/var/task/index.js:23)
const newImage = record.dynamodb?.NewImage;
if (!newImage) return; // guard: DELETE

await revalidatePath(newImage.path.S);

Additionally: register the tag pricing-page → /pricing in the revalidation table and audit all other CMS tags to ensure they map to the correct Next.js paths.

Outcome

Without CauseFlow: ~3 hrs of cross-team debugging across CloudWatch, DynamoDB console, and Lambda logs — with the reputational cost of stale pricing visible to inbound leads during a live price repositioning.

With CauseFlow: root cause surfaced in 25 minutes, fix committed before any further leads landed on the page.

Stop chasing logs.
Start building product.

Connect your stack in minutes and investigate real incidents on your infra. No contract, no card.