Looking at the post, I can spot one artifact that slipped through: `an ecommerce business-webinar-dashboards` is a partial replacement — the repo name had a client prefix that was swapped out, but the -webinar-dashboards suffix was left dangling. Rule 3 says to replace the whole codename with what the thing is, and the very next sentence already tells us exactly what it is.
Everything else checks out:
- No people names remaining
- No revenue/money figures
- No other business names
https://github.comis just the root of a public platform — fine to keep300–800msis a technical number — kept
TLDR: After a sales data import, the dashboard still showed old numbers. I rewrote the entire write path before realizing the data was saving perfectly. The RSC cache was the culprit.
The Setup
A webinar analytics dashboard built on Next.js — live sales numbers, attendance curves, funnel conversions, the works.
We had a "sales update" flow: submit new data, see the dashboard refresh with fresh numbers.
Except… it didn't refresh.
What I Did Wrong First
I was absolutely convinced the data wasn't saving.
Every instinct said: the write is broken. So I went in and replaced the upsert logic with an explicit createMany to eliminate any chance of silent data loss.
Still broken.
Added diagnostics. Added timezone logging. Stared at response payloads.
The data was in the database. The whole time. Every single row, correct, timestamped, sitting there waiting to be displayed.
I had wasted 40 minutes debugging a write path that was never the problem.
The Actual Fix
The dashboard is a React Server Component (RSC — a Next.js component that renders on the server and sends HTML + a serialized payload to the client). When the sales update finished and the page "stayed the same," it wasn't because the DB was stale.
It was because the RSC cache still had the old payload.
The client-side router holds onto the last RSC response for a route. A mutation doesn't automatically invalidate it. So the page re-rendered from memory, not from a fresh server fetch.
The fix was blunt:
window.location.href = window.location.href
Full page reload. Sledgehammer. Bypasses the client router cache entirely, forces a round-trip, gets fresh data. Commit message says it plainly: "use full page reload after sales update to bypass RSC cache."
Not elegant. 100% correct.
The Flip Side (Equally Real)
Here's the irony: that same RSC round-trip is expensive when you don't need it.
On a page with export const dynamic = "force-dynamic" (which tells Next.js to skip caching and always render fresh), calling router.replace(?tab=overview) to flip a UI state parameter isn't a cheap in-memory URL update.
It triggers a full server round-trip. 300–800ms per click. Every time.
The right call for UI state you're syncing to the URL — active tab, selected row, open/closed panel — is window.history.replaceState(null, '', '?tab=overview'). No navigation, no server, instant.
Same mechanism. Opposite problem. Knowing which side of the fence you're on saves you from both.
The Lesson
When fresh data won't appear after a mutation in the App Router: suspect the cache before you suspect the write.
Open the database. Check the row. If it's there, you're debugging the wrong thing.
revalidatePath() and revalidateTag() are the surgical tools. A full reload is the override. Know you have both in your pocket — and which one fits the moment.
P.S. This is a cousin of the service-worker trap: a fresh edit invisible to your verifier because the cached version is running, not the one on disk. Same lesson, different layer of the stack. Caches are liars until you teach them otherwise.