How a React Query Hydration Loop Slowed Down My Next.js App

April 12, 2025

🐢 Why Did My Next.js Routing Suddenly Slow Down?

Client-side routing in my Next.js app had always been snappy — until one day, it wasn’t.   Out of nowhere, navigating between pages would freeze for several seconds.

What made it more confusing was this:   as soon as I interacted with the UI — like opening a popup — the delay vanished.   Since I had SSR and caching in place, I quickly ruled out server-side causes.

This had to be a client-side issue.


Step 1: Profiling the Performance

I opened Chrome DevTools and started recording a performance profile.

DevTools spike

Immediately, a massive spike showed up.   It was so heavy that DevTools crashed mid-recording.   Something was clearly stuck in an infinite loop.

To get a better view, I needed to analyze the bundle.   But there was a problem…


Step 2: Analyzing the Bundle (Without Minification)

As of Next.js 15, customizing the minifier isn’t supported anymore. Minify setting gone

So instead, I used the Bundle Analyzer to inspect what was bloating the bundle.


The Culprit: @tanstack/react-query

Surprisingly, the problem was coming from @tanstack/react-query.

That caught me off guard — the only place I used it during routing was inside HydrationBoundary for SSR.  

Could this be a hydration loop?

Let’s look at the source:


React.useMemo(() => {

  if (state) {

    // Updates hydrationQueue

  }

}, [client, hydrationQueue, state]);

  

React.useEffect(() => {

  if (hydrationQueue) {

    hydrate(client, { queries: hydrationQueue }, optionsRef.current);

    setHydrationQueue(undefined);

  }

}, [client, hydrationQueue]);

Looks like useMemo and useEffect are creating a loop through hydrationQueue. I added a simple console.log inside the effect, and sure enough — it was firing constantly.

Local Fix (That Worked)

It seemed like useMemo only needed to re-run when state changed. So I removed hydrationQueue from its dependency list.

With that one change, the issue was gone. Routing was fast and responsive again. ✅

But I Didn’t Ship That Fix

Even though this fixed the problem locally, I came across this issue on GitHub describing the same behavior.

A comment on the original PR clarified the intent:

The loop was introduced as part of a broader strategy to ensure hydration works in more cases. Removing hydrationQueue from deps might break things elsewhere.

In other words, the maintainers probably already considered this “fix” — and decided against it for good reason.

My Final Decision

Rather than risk unintended behavior, I decided to downgrade to @tanstack/react-query@5.66.3, the last version before this change was introduced.

⚠️ Versions 5.66.4 through 5.72.3 (latest at time of writing) still contain the issue.

That downgrade brought stability back — no infinite loops, no routing lag.

Summary

• If your Next.js routing is slow, consider profiling for infinite render loops. • @tanstack/react-query introduced a hydration issue in versions after 5.66.3. • A local patch might work, but isn’t future-proof. • Downgrading is the safest solution — for now.