{"slug": "case-study-persisted-tanstack-query-mutations", "title": "Case Study: Persisted TanStack Query Mutations", "summary": "A case study comparing Codex GPT-5.5 runs with and without GitHits found that GitHits reduced token usage by 66% and tool calls by 46% while fixing a persisted TanStack Query mutation issue in a React checkout flow. The bug occurred because a persisted paused mutation lacked a default mutation function after reload, which was resolved by registering the mutation function on the QueryClient.", "body_md": "[Back to blog](/blog/)\n\nJune 15, 2026 · 3 min read\n\n# Case Study: Persisted TanStack Query Mutations\n\nA measured Codex run fixing a persisted TanStack Query mutation by finding the default mutation function rule.\n\nThe fixture is a React checkout flow using TanStack Query persistence.\n\nThe user places an order while offline. TanStack Query pauses the mutation. The\napp persists the query cache. After reload, the app restores the cache, goes\nonline, and calls `resumePausedMutations()`\n\n.\n\nExpected result: the order is submitted once after reload.\n\nActual result: the order is never submitted.\n\nBoth runs used Codex GPT-5.5 against the same fixture. The prompt was:\n\n```\nFix this TypeScript React fixture so `npm test` and `npm run typecheck` succeed, preserving queued checkout writes across app reloads.\n```\n\nThe target packages were `@tanstack/react-query 5.101.0`\n\nand `@tanstack/react-query-persist-client 5.101.0`\n\n.\n\nCase study replay\n\n## TanStack Query persisted checkout outbox\n\nmodel Codex GPT-5.5Fix this TypeScript React fixture so `npm test` and `npm run typecheck` succeed, preserving queued checkout writes across app reloads.\n\nWithout GitHits\n\n- tokens\n- 0\n- time\n- 0s / 126s\n\n- Ready. Click \"Watch Replay\" to start.\n- Reached the same mutation-default fix, but first installed dependencies and reconstructed the persistence path from local TanStack Query internals.\n\nWith GitHits\n\n- tokens\n- 0\n- time\n- 0s / 79s\n\n- Ready. Click \"Watch Replay\" to start.\n- Used TanStack Query persistence docs to register a keyed mutation default, allowing hydrated paused checkout writes to resume after reload.\n\n## Result\n\n| Run | Time | Tokens | Tools |\n|---|---|---|---|\n| With GitHits | 79s | 350,965 | 19 |\n| Without GitHits | 126s | 1,031,661 | 35 |\n\nBoth runs produced a passing patch. The GitHits run used 680,696 fewer processed tokens and 16 fewer tool calls.\n\n## Failure\n\nThe fixture created a `QueryClient`\n\nwithout mutation defaults:\n\n```\nexport function createCheckoutClient(_api?: CheckoutApi): QueryClient {\n  return new QueryClient({\n    defaultOptions: {\n      queries: { retry: false },\n      mutations: { retry: false },\n    },\n  });\n}\n```\n\nThe checkout component passed the mutation function to `useMutation`\n\n:\n\n``` js\nconst submitOrder = useMutation({\n  mutationKey: submitOrderMutationKey,\n  mutationFn: api.submitOrder,\n});\n```\n\nThat function exists only in the mounted component. After persistence and reload, the restored mutation has its key and state. It does not have the component closure.\n\nThe relevant TanStack Query rule: a persisted paused mutation needs a default mutation function registered for its mutation key before it can resume.\n\n## Fix\n\nRegister the checkout submit function on the client:\n\n``` js\nexport function createCheckoutClient(api?: CheckoutApi): QueryClient {\n  const client = new QueryClient({\n    defaultOptions: {\n      queries: { retry: false },\n      mutations: { retry: false },\n    },\n  });\n\n  if (api) {\n    client.setMutationDefaults(submitOrderMutationKey, {\n      mutationFn: api.submitOrder,\n    });\n  }\n\n  return client;\n}\n```\n\nThe test restores an offline write into a fresh client, goes online, resumes paused mutations, and checks that the checkout API receives the original order once.\n\n## Trace\n\nThe GitHits run found the rule with docs search:\n\n```\nsearch target=npm:@tanstack/react-query@5.101.0 source=docs query=persistQueryClient resumePausedMutations mutation defaults offline persistence reload limit=5\ndocs_read page_id=20025 start_line=1 end_line=120\ndocs_read page_id=20025 start_line=340 end_line=416\n```\n\nIt then patched `createCheckoutClient`\n\nand ran:\n\n```\nnpm test\nnpm run typecheck\n```\n\nThe no-GitHits run installed dependencies and searched local package source for the same behavior. It read TanStack Query hydration, mutation cache, query client defaults, and default mutation option code before editing.\n\nIn this run, docs search found the package contract directly. The agent did not need to inspect source internals to discover it.", "url": "https://wpnews.pro/news/case-study-persisted-tanstack-query-mutations", "canonical_source": "https://githits.com/blog/tanstack-query-checkout-outbox-case-study/", "published_at": "2026-06-15 00:00:00+00:00", "updated_at": "2026-06-16 07:54:32.590769+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "ai-tools"], "entities": ["TanStack Query", "Codex GPT-5.5", "GitHits", "React", "TypeScript"], "alternates": {"html": "https://wpnews.pro/news/case-study-persisted-tanstack-query-mutations", "markdown": "https://wpnews.pro/news/case-study-persisted-tanstack-query-mutations.md", "text": "https://wpnews.pro/news/case-study-persisted-tanstack-query-mutations.txt", "jsonld": "https://wpnews.pro/news/case-study-persisted-tanstack-query-mutations.jsonld"}}