[Canonical HTML page](https://githits.com/blog/tanstack-query-checkout-outbox-case-study/)

[Back to blog](/blog.md)

![A queued mutation moving through persisted storage, resuming after a break, and completing successfully](/_astro/tanstack-query-checkout-outbox-case-study-v2.DwFhMlLE_ZDLq3k.webp)

June 15, 2026 · 3 min read

# Resuming persisted mutations in TanStack Query

How Codex fixed an offline checkout mutation that stopped working after reload.

We tested a React checkout flow that uses TanStack Query persistence. A customer places an order offline, the mutation pauses, and the app saves the query cache. After a reload, the app restores the cache and calls `resumePausedMutations()`.

The order should be submitted once. Instead, nothing happened.

Both runs used Codex GPT-5.5 against `@tanstack/react-query 5.101.0` and `@tanstack/react-query-persist-client 5.101.0` with the same prompt:

```text
Fix this TypeScript React fixture so `npm test` and `npm run typecheck` succeed, preserving queued checkout writes across app reloads.
```

Case study replay

## TanStack Query persisted checkout outbox

model — Codex GPT-5.5

Fix this TypeScript React fixture so \`npm test\` and \`npm run typecheck\` succeed, preserving queued checkout writes across app reloads.

Without GitHits

Costly

1. Reached the same mutation-default fix, but first installed dependencies and reconstructed the persistence path from local TanStack Query internals.

With GitHits

Efficient

1. Used TanStack Query persistence docs to register a keyed mutation default, allowing hydrated paused checkout writes to resume after reload.

## Result

| Run             | Time | Tokens    | Tools |
| --------------- | ---- | --------- | ----- |
| With GitHits    | 79s  | 350,965   | 19    |
| Without GitHits | 126s | 1,031,661 | 35    |

Both runs produced a passing patch. The GitHits run used 680,696 fewer processed tokens and 16 fewer tool calls.

## Why the mutation stopped

The fixture created a `QueryClient` without mutation defaults:

```tsx
export function createCheckoutClient(_api?: CheckoutApi): QueryClient {
  return new QueryClient({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  });
}
```

The component supplied the function when it called `useMutation`:

```tsx
const submitOrder = useMutation({
  mutationKey: submitOrderMutationKey,
  mutationFn: api.submitOrder,
});
```

That function belongs to the mounted component. The persisted mutation keeps its key and state after reload, but not the component closure. TanStack Query needs a default mutation function for the same key before it can resume the work.

## The fix

The patch registered the submit function on the client:

```tsx
export function createCheckoutClient(api?: CheckoutApi): QueryClient {
  const client = new QueryClient({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  });

  if (api) {
    client.setMutationDefaults(submitOrderMutationKey, {
      mutationFn: api.submitOrder,
    });
  }

  return client;
}
```

The test restores the offline write into a fresh client, goes online, resumes paused mutations, and checks that the API receives the original order once.

## What GitHits changed

Both runs found the same fix. The GitHits run finished 47 seconds sooner, used 680,696 fewer processed tokens, and needed 16 fewer tool calls.

GitHits found the persistence guide for TanStack Query `5.101.0`. It states the missing requirement directly: after hydration, a paused mutation can only resume if the client has a default mutation function for its key. Codex could then add `setMutationDefaults`, run the tests, and typecheck the fixture.

Without GitHits, Codex installed the dependencies and traced the rule through hydration, mutation cache, query client defaults, and mutation option code. The final patch was identical, but GitHits replaced that source-level investigation with one version-matched documentation path.

[Case Study](/blog/tag/case-study.md) · [Agents](/blog/tag/agents.md) · [TypeScript](/blog/tag/typescript.md) · [React](/blog/tag/react.md)

Olli-Pekka Heinisuo — Co-founder, CTO

Keep exploring

* [The Solution](/the-solution.md)
* [Documentation](https://docs.githits.com/)
* [Changelog](https://docs.githits.com/changelog/overview)

Get started

## GitHits in one command

Install GitHits or refresh an existing setup with the same command.

`npx -y githits@latest init`
