# Polling

> Refetch a query on an interval while it's on screen with meta.refetchInterval and the polling() feature.

A query with `meta: { refetchInterval }` refetches every so many milliseconds while a component reads it:

```ts
export function buildQuery(input: { id: string }) {
	return queryOptions({
		queryKey: builds(input.id),
		queryFn: () => getBuild(input.id),
		meta: { refetchInterval: 2000 },
	});
}
```

The `polling()` feature reads that field, so the client needs it, on its own or through `recommended()`:

```ts
const queryClient = createQueryClient({ features: [polling()] });
// or
const sameWithMore = createQueryClient({ ...recommended() });
```

On a client without `polling()`, `refetchInterval` does nothing. A factory built with a bound `queryOptions` gets the field typed only when the root has the feature: see [Query meta](https://raf-query.katt.dev/docs/query-meta.md#typing-meta-by-its-root).

- Polling starts when the first component reads the query, and stops when the last one unmounts.
- There is one timer per query, however many components read it.
- A poll that lands while another request for the query is in flight joins it instead of starting a second one.
- Features run while a `QueryClientProvider` has the client mounted, so the server never polls.

Each poll is a background refetch: the data on screen stays put. Structural sharing keeps a response equal to the current data from changing the data's identity, so memoized children don't re-render.

> [!NOTE]
> The [web version of this page](https://raf-query.katt.dev/docs/polling) has an interactive demo here. Its code: [polling.tsx](https://github.com/KATT/raf-query/blob/main/www/src/demos/polling.tsx).

## The interval per input

The interval is part of the query's options, so a factory can compute it from its input:

```ts
export function buildLogQuery(input: { id: string; live: boolean }) {
	return queryOptions({
		queryKey: builds("log", input),
		queryFn: () => getBuild(input.id),
		meta: { refetchInterval: input.live ? 1000 : false },
	});
}
```

`false` or `0` turns polling off. Each input is its own query, so this picks the interval per query; it can't change while the same query is read.

## Polling and staleTime

Polling refetches whatever the data's `staleTime`: the interval is an explicit request for fresh data. Keep `staleTime` meaningful anyway, because the loaders that start the same query rely on it.
