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: 50fc68ff-1970-4e4a-ad60-d7a1f7ac0c18

📥 提交

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

📒 Files selected for processing (1)
  • packages/query-core/src/removable.ts

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


📝 Walkthrough

Walkthrough

The query core now skips garbage collection timer scheduling in server environments, including queries with explicit finite gcTime. A regression test verifies this behavior, and a patch changeset documents the 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 declares a patch release.

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

Merge Risk: ⚪ Minimal · up to 9c528

The change prevents unnecessary garbage-collection timers during server rendering while preserving client-side scheduling and the existing opt-in server override. No actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: tkdodo

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked 问题 check ✅ Passed The implementation satisfies issue #11320 by making scheduleGc() return early on the server, preserving gcTime, keeping client behavior unchanged, and retaining the server opt-in through environmentMa…
Out of Scope Changes check ✅ Passed The changes are limited to the requested server-side GC scheduling fix, its regression test, and the required changeset. No unrelated code 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…
Title check ✅ Passed The title clearly and concisely describes the main change: preventing garbage-collection scheduling on the server in query-core.
Description check ✅ Passed The description is complete and relevant. It explains the server-side timer issue, the implementation, expected behavior, opt-in behavior, testing, checklist completion, and release impact.
Full details: Linked 问题 check

Explanation

The implementation satisfies issue #11320 by making scheduleGc() return early on the server, preserving gcTime, keeping client behavior unchanged, and retaining the server opt-in through environmentManager.setIsServer(() => false).

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 比较 August 28, 2026 07:36
注册 for free to join this conversation on GitHub. Already have an account? 登录 to comment

标签

None yet

项目

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