TanStack/query’s critical risk is concentrated in two layers: the experimental query persistence API and the v5 codemod infrastructure. Across 3,031 total functions, 84 are flagged critical; the top 5 hotspots all occupy the fire quadrant (complex and actively changing), with activity_risk scores between 15.44 and 16.82. Four of the five exhibit deeply nested control flow (ND 5–6) and exit-heavy patterns—multiple return paths that increase test-case burden and regression risk.
The table below ranks functions by activity-weighted risk — a score that multiplies structural complexity by recent commit frequency. A function that is both hard to understand (high cyclomatic complexity) and actively changing is a higher priority than one that is complex but untouched. CC = cyclomatic complexity (independent execution paths); ND = max nesting depth; FO = fan-out (distinct callees).
Top 5 Hotspots
| Function | File | Risk | CC | ND | FO |
|---|---|---|---|---|---|
experimental_createQueryPersister | packages/query-persist-client-core/src/createPersister.ts | 16.8 | 14 | 6 | 27 |
<anonymous> | …/query-codemods/…/filter-aware-usage-transformer.cjs | 16.3 | 23 | 5 | 20 |
<anonymous> | …/query-codemods/…/filter-aware-usage-transformer.cjs | 15.7 | 11 | 5 | 30 |
restoreQueries | packages/query-persist-client-core/src/createPersister.ts | 15.6 | 19 | 6 | 8 |
Explorer | packages/query-devtools/src/Explorer.tsx | 15.4 | 26 | 3 | 38 |
Codemod / Tooling Files in Results
Rows 2 and 3 in the table above are two distinct anonymous functions inside packages/query-codemods/src/v5/remove-overloads/transformers/filter-aware-usage-transformer.cjs. This is a codemod tooling file—not core query logic—that scores high due to the structural complexity of AST transformation (CC 23 and 11, fan-out 20 and 30). Codemods are maintenance-time tools; high CC here reflects the combinatorial logic of matching and rewriting AST nodes, not production risk. If you want to focus your analysis on core library code, add this to .hotspotsrc.json: "exclude": ["packages/query-codemods/**"].
Hotspot Analysis
experimental_createQueryPersister — packages/query-persist-client-core/src/createPersister.ts
This experimental persistence factory has the highest activity_risk (16.82) and sits squarely in the fire quadrant. Its CC of 14 indicates moderate-to-high branching complexity; the ND of 6 reveals deeply nested control structures that make reasoning about state transitions difficult. With a fan-out of 27, changes here have broad coupling implications across the persistence subsystem. The experimental_ prefix signals this API is not yet stable—high activity combined with structural complexity means the team is iterating on logic that affects query hydration and cache restoration.
Recommendation: Before refactoring, map the 27 callees to identify which ones handle critical paths (e.g., cache validation, retry logic). Extract independent orchestration steps into smaller, testable functions; in particular, isolate branching logic that decides whether to restore vs. discard persisted state. Add characterization tests to lock down current behavior before simplifying nesting depth.
restoreQueries — packages/query-persist-client-core/src/createPersister.ts
restoreQueries runs at app initialization: it reads serialized query state from the persistence backend (IndexedDB, localStorage, etc.) and decides which cached results are still valid to hydrate back into the QueryClient. CC 19 means 19 independent decision paths through that initialization logic—every branch is a different answer to “is this persisted query still usable?” Max nesting depth of 6 makes those decisions hard to follow in sequence. Despite lower fan-out (8), the exit-heavy pattern scatters the success/failure/expiry validation across multiple early returns rather than concentrating it at the top.
Recommendation: Extract validation and recovery logic into named helper functions (e.g., isRestoredQueryValid, applyRestoredQueryState). Replace early returns with a clear state machine or decision table at the top level. This will reduce ND and make test coverage for each recovery path explicit.
Explorer — packages/query-devtools/src/Explorer.tsx
The Explorer component is a god_function in the devtools layer: CC 26 indicates many conditional branches, and fan-out of 38 means it orchestrates broadly across the devtools UI. Unlike the persistence functions, its ND is moderate (3), but the combination of high CC with 38 distinct function calls—plus recent churn (activity_risk 15.44)—suggests it is a hub for state inspection and mutation. The exit-heavy pattern compounds the coupling risk: changes to branching logic ripple across many dependents.
Recommendation: Decompose by feature or inspection mode: separate query list rendering, filter logic, and cache inspection into isolated child components or hooks. This will reduce fan-out and CC simultaneously. Add snapshot tests for each mode before refactoring to catch unintended UI regressions.
Patterns Found
Antipatterns detected across the top functions in this snapshot:
| Pattern | Occurrences |
|---|---|
exit_heavy | 5 |
complex_branching | 4 |
deeply_nested | 4 |
god_function | 4 |
long_function | 4 |
That all five top hotspots share this exact cluster is itself a finding: structural debt isn’t isolated to one poorly-written function — it’s a consistent style across the persistence, codemod, and devtools layers simultaneously.
These labels belong to two tiers — Tier 1 (structural): complex_branching, deeply_nested, exit_heavy, long_function, god_function. Tier 2 (relational/temporal): hub_function, cyclic_hub, middle_man, neighbor_risk, stale_complex, churn_magnet, shotgun_target, volatile_god.
Key Takeaways
- experimental_createQueryPersister and restoreQueries both have activity_risk > 15 and ND ≥ 6; prioritize reducing nesting depth in the persistence layer before the API graduates from experimental status.
- The Explorer devtools component couples 38 distinct callees with CC 26; extract presentation logic into focused subcomponents to isolate UI changes from state-inspection refactors.
- All 5 top hotspots exhibit exit-heavy patterns (multiple returns); introduce guard clauses and decision points at function entry to concentrate control flow, which will also improve test coverage clarity.
Reproduce This Analysis
git clone https://github.com/TanStack/query
cd query
git checkout 391db367b3e7adeff9a0dd647474d1575a31a787
hotspots analyze . --mode snapshot
Hotspots highlights structural and activity risk — not “bad code.” Findings are a prioritization aid, not a bug predictor. Editorial policy →