Capítulo 21 de 80

Chapter 21: Query Retries

Core Idea

Failed queries retry automatically with exponential backoff (default 3 attempts, capped delay), configurable per-query or globally, with SSR defaulting retries to 0 for fast server renders.

Key Concepts

  • retry option: false disables retries; a number retries that many times before surfacing the final error; true retries forever; a function (failureCount, error) => boolean gives full custom logic (failureCount starts at 0 on the first retry).
  • SSR default: retries default to 0 on the server, so server rendering doesn't stall waiting on retry backoff.
  • failureReason vs error: while retries are still in progress, the latest error is exposed via failureReason; only after the final retry attempt does it move to error.
  • retryDelay: defaults to exponential backoff starting at 1000ms, doubling per attempt, capped at 30s (Math.min(1000 * 2 ** attemptIndex, 30000)) — configurable globally (via QueryClient defaults) or per-query; a static number instead of a function makes every retry wait the same fixed delay.
  • Retries pause with background refetches: when refetchIntervalInBackground: true is set, retries still pause in an inactive tab because they share the same focus-based gating as normal refetches — to keep retrying in the background, disable built-in retry and drive a custom refetchInterval function instead (e.g. polling faster while in an error state).

Code Examples

// Retry up to 10 times with default backoff
useQuery({ queryKey: ['todos', 1], queryFn: fetchTodoListPage, retry: 10 })

// Global backoff config, capped at 30s
const queryClient = new QueryClient({
  defaultOptions: {
    queries: { retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000) },
  },
})
  • What it demonstrates: overriding retry count per-query, and configuring the default exponential-backoff delay globally.

Reference Tables

retry valueBehavior
falseNo retries
3 (default)Retry 3 times, then surface the error
trueRetry indefinitely
(failureCount, error) => booleanCustom retry logic

Key Takeaways

  1. Read failureReason (not error) to show interim failures while retries are still pending — error only populates after the final attempt.
  2. SSR retries default to 0 for a reason — don't override this without accounting for slower server response times.
  3. To retry continuously in a backgrounded tab, disable built-in retry and drive the retry logic yourself through a refetchInterval function — built-in retries pause with the tab like any other background refetch.

Connects To

  • Important Defaults: the retry/backoff numbers referenced here as defaults.
  • Polling: the refetchIntervalInBackground mechanism this chapter's background-retry workaround builds on.