Skip to content

fix(query-core): do not schedule garbage collection on the server - #11321

Open
AdzerKI wants to merge 1 commit into
TanStack:mainfrom
AdzerKI:fix/no-gc-timer-on-server
Open

fix(query-core): do not schedule garbage collection on the server#11321
AdzerKI wants to merge 1 commit into
TanStack:mainfrom
AdzerKI:fix/no-gc-timer-on-server

Conversation

@AdzerKI

@AdzerKI AdzerKI commented Aug 28, 2026

Copy link
Copy Markdown

🎯 Changes

Fixes #11320.

updateGcTime falls back to Infinity on the server, so by default nothing is scheduled there. An explicit finite gcTime bypasses that fallback, and scheduleGc() then schedules a timer during server rendering.

A Node timer captures the async context it is created in, so it keeps the whole SSR render alive until it fires: the framework's request store, the react-dom/server Request, the produced HTML and the RSC payload. It cannot clean up anything either — the per-request client is unreachable long before gcTime elapses.

scheduleGc() now returns early on the server. The gcTime value is untouched; nothing else reads it there. Long-lived Node processes that do want garbage collection opt in with environmentManager.setIsServer(() => false).

Reproduction from the issue — 2000 simulated renders, 512 KB of render context each, forced GC before measuring:

before, gcTime 60_000:  pendingTimers=2000  external=1001MB  rss=1068MB
after,  gcTime 60_000:  pendingTimers=0     external=1MB     rss=116MB

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with pnpm run test:pr, or these tests do not apply to this pull request. (Ran test:eslint, test:lib, test:types, test:build and build for query-core and react-query: 647 + 571 tests green.)
  • I fully understand the code in this pull request, including any code generated with AI assistance.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • Bug Fixes

    • Improved server-side rendering by preventing unnecessary garbage-collection timers from keeping renders alive.
    • Queries with explicitly configured finite cache lifetimes are no longer scheduled for garbage collection on the server, while client-side behavior remains unchanged.
  • Tests

    • Added coverage to verify that server-rendered queries do not schedule garbage-collection timers.

@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0f14bc77-d710-4958-8cd1-25e3590cee0a

📥 Commits

Reviewing files that changed from the base of the PR and between 9c52898 and ac3f37e.

📒 Files selected for processing (1)
  • packages/query-core/src/__tests__/query.test.tsx

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The query core skips garbage collection timer scheduling in server environments, including queries with finite gcTime. A regression test verifies the behavior, and a changeset declares a patch release.

Changes

Server garbage collection

Layer / File(s) Summary
Skip server GC timers
packages/query-core/src/removable.ts, packages/query-core/src/__tests__/query.test.tsx, .changeset/quiet-timers-rest.md
scheduleGc returns early on the server. The test verifies that finite gcTime remains configured without calling timeoutManager.setTimeout. The changeset documents the patch release.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to ac3f3

The change prevents unnecessary server-side garbage-collection timers while preserving configured values and client-side scheduling behavior; no actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: tkdodo, sukvvon

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the primary change: preventing garbage-collection scheduling on the server in query-core.
Description check ✅ Passed The description includes the required Changes, Checklist, and Release Impact sections. It explains the problem, implementation, testing, and changeset status.
Linked Issues check ✅ Passed The implementation satisfies issue #11320. It prevents server-side GC timers for finite gcTime values, preserves gcTime, keeps client behavior unchanged, and documents the server opt-in path.
Out of Scope Changes check ✅ Passed The code change, regression test, and patch changeset directly support the linked issue and stated objectives. No unrelated changes are identified.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AdzerKI
AdzerKI force-pushed the fix/no-gc-timer-on-server branch from ce346d7 to 9c52898 Compare August 28, 2026 07:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server-side gcTime schedules a GC timer that pins the whole SSR async context

1 participant