TLDR: I spent two deploys guessing at the wrong things. One targeted diagnostic commit found it in minutes. The bug was a timezone offset — server-rendered timestamps running UTC on Vercel while an ecommerce business operates on ET.

The Setup

I've been building an analytics dashboard for an ecommerce client's webinar program.

After a sales update, the viewer timeline data was wrong.

Not silently wrong. Visibly wrong — the content-start timing was off, and the pitch-window analysis was landing in the wrong place on the chart.

Two Guesses That Cost Me Two Deploys Each

My first instinct was data integrity.

Maybe the upsert was silently dropping rows — some RETURNING behavior I wasn't seeing.

So I shipped: fix: use explicit createMany for sales update to prevent silent data loss.

Nothing changed.

Okay. New theory. RSC cache (React Server Component cache, Next.js's aggressive server-side memoization) serving stale data after the mutation. Classic. I'd hit this before.

So I shipped: fix: use full page reload after sales update to bypass RSC cache.

Still nothing.

Two deploys. Two plausible theories. Zero progress.

The Shift: Stop Guessing, Start Instrumenting

Here's the thing — both those guesses were reasonable. That's exactly why they're dangerous. When a guess sounds right, you ship it and wait. And when it doesn't fix anything, you've burned time and still have no information.

So I stopped guessing and started adding diagnostics directly into the response.

debug: add sales update diagnostics to trace missing timeline data

That gave me the data shape. Still murky. So I got more specific.

debug: add timezone diagnostics to sales update response

And there it was.

What the Diagnostics Actually Showed

On Vercel (where the app deploys), server components run in UTC — not the user's local timezone.

So any date computation happening at render time on the server was UTC-anchored. The contentStart value — the timestamp used to anchor the whole pitch-window analysis — was being derived server-side, where Vercel treats new Date() as UTC.

an ecommerce business operates on ET. A webinar that starts at 8pm ET was being read as midnight UTC — the next day. The timeline wasn't corrupt. It was just anchored to the wrong moment.

(The general rule: toLocaleString() and raw new Date() in a Server Component will render in the server's timezone — UTC on Vercel, not the browser's TZ. Client components are fine. Server components are not.)

The Fix

Instead of deriving contentStart from a server-computed timestamp, I pulled it from the viewer timeline labels — data that's already ET-anchored from the source.

fix: derive contentStart from viewer timeline labels to fix timezone offset

Then I cleaned it all out: chore: remove sales update debug diagnostics.

The diagnostics were scaffolding. Once you find the bug, you tear it down.

Why This Matters to Me

I've been bitten by timezone bugs before. What's different this time is the discipline.

The instinct to ship a plausible fix is strong — especially when the fix genuinely could be right. But two plausible fixes that don't work leave you in the same fog you started in, just later.

One targeted diagnostic commit found the real answer in one round. That's the trade I want to make every time.

Instrument the actual response. Read what it tells you. Fix that. Remove the scaffolding.

P.S. If you're building on Next.js + Vercel and your dates look off for non-UTC users — check whether the computation is happening in a Server Component. It almost certainly is.