> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/get-convex/convex-react-query/llms.txt
> Use this file to discover all available pages before exploring further.

# Server-side rendering

> Fetch Convex data on the server and hydrate the TanStack Query cache for SSR frameworks.

`ConvexQueryClient` supports SSR by using `ConvexHttpClient` to fetch query results on the server. On the client, the WebSocket subscription takes over and keeps data live.

## How it works

* On the server (`typeof window === "undefined"`), `convexQueryClient.queryFn()` uses `ConvexHttpClient` to make HTTP requests instead of opening a WebSocket subscription.
* By default, SSR fetches use **consistent mode**: multiple queries are fetched from the same logical database snapshot. This prevents inconsistencies when your UI joins data across multiple queries.
* You can opt out with `dangerouslyUseInconsistentQueriesDuringSSR: true` for a faster but potentially inconsistent SSR render.

## Basic SSR setup

Construct `ConvexQueryClient` with a `serverFetch` option to supply a custom fetch implementation for server-side HTTP requests.

```ts theme={null}
import { ConvexQueryClient } from "@convex-dev/react-query";
import { ConvexReactClient } from "convex/react";

const convexClient = new ConvexReactClient(process.env.CONVEX_URL!);
const convexQueryClient = new ConvexQueryClient(convexClient, {
  // Provide a custom fetch for server-only usage
  serverFetch: fetch,
});
```

## Consistent vs. inconsistent SSR queries

<CodeGroup>
  ```ts Consistent (default) theme={null}
  // Default: consistent mode — two round trips, consistent snapshot
  const convexQueryClient = new ConvexQueryClient(convexClient);
  ```

  ```ts Inconsistent (opt out) theme={null}
  // Opt out: one round trip, potentially inconsistent across queries
  const convexQueryClient = new ConvexQueryClient(convexClient, {
    dangerouslyUseInconsistentQueriesDuringSSR: true,
  });
  ```
</CodeGroup>

## Why consistent queries matter

When your React code joins data from multiple queries, both queries must reflect the same database state. In consistent mode, Convex guarantees this on the server.

```tsx theme={null}
// These two queries will always be from the same database snapshot in consistent mode.
// In inconsistent mode, they could disagree (a favChannelId with no matching channel).
const channels = useQuery(convexQuery(api.channels.all, {}));
const favChannelIds = useQuery(convexQuery(api.channels.favIds, {}));
const favChannels = channels && favChannelIds
  ? favChannelIds.map((id) => channels[id])
  : [];
```

In inconsistent mode, `favChannelIds` could reference channel IDs that don't yet exist in `channels` because the two HTTP requests may have hit different database snapshots.

## Using with TanStack Start

In TanStack Start, use `createServerOnlyFn` to ensure the `serverFetch` implementation is never bundled into the client.

```ts theme={null}
import { createServerOnlyFn } from "@tanstack/start";

const convexQueryClient = new ConvexQueryClient(convexClient, {
  serverFetch: createServerOnlyFn().handler(fetch),
});
```

<Warning>
  The `serverFetch` option should be server-only code. In TanStack Start, wrap
  it with `createServerOnlyFn` to avoid bundling it on the client.
</Warning>

<Info>
  During client-side navigation, the WebSocket subscription is used — SSR only
  affects the initial server render.
</Info>
