> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Replica-aware routing

> Route related requests to the same ClickHouse Cloud replica for temporary tables, sessions, cache reuse, and read-after-write consistency

export const PrivatePreviewBadge = () => {
  return <div className="privatePreviewBadge">
            <div className="privatePreviewIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M5.33301 6.66667V4.66667V4.66667C5.33301 3.194 6.52701 2 7.99967 2V2C9.47234 2 10.6663 3.194 10.6663 4.66667V4.66667V6.66667" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path d="M8.00033 9.33337V11.3334" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path fillRule="evenodd" clipRule="evenodd" d="M11.333 14H4.66634C3.92967 14 3.33301 13.4033 3.33301 12.6666V7.99996C3.33301 7.26329 3.92967 6.66663 4.66634 6.66663H11.333C12.0697 6.66663 12.6663 7.26329 12.6663 7.99996V12.6666C12.6663 13.4033 12.0697 14 11.333 14Z" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            {'Private preview in ClickHouse Cloud'}
        </div>;
};

<PrivatePreviewBadge />

Replica-aware routing (also known as sticky sessions, sticky routing, or session affinity) routes related requests to the same ClickHouse replica. Use it when you need [temporary tables](/docs/sql-reference/statements/create/table#temporary-tables) or [named session state](/docs/interfaces/http#using-clickhouse-sessions-in-the-http-protocol) to stay reachable across queries, when you want related queries to reuse the same replica's local caches, or when you need [read-after-write consistency](#read-after-write-consistency) across a write and its follow-up reads.

It's best-effort and doesn't guarantee isolation. Scaling, upgrades, and restarts can remap which replica a given `session_id` lands on.

<Warning>
  **Requires the HTTP interface**

  Replica-aware routing is applied at the proxy layer over the [HTTP/HTTPS interface](/docs/interfaces/http), using the `session_id` query parameter (see below). It's **not available over the native protocol** (native port, e.g. the [clickhouse-go](/docs/integrations/go) driver in its default native mode). Native-protocol clients must switch to HTTP and pass a `session_id` on each request. For clickhouse-go (v2), set `Protocol: clickhouse.HTTP` and pass `session_id` as a [setting](/docs/integrations/language-clients/go/database-sql-api#sessions). The driver sends it as the URL query parameter the proxy hashes on.
</Warning>

<h2 id="prerequisites">
  Prerequisites
</h2>

* Your service needs **2 or more replicas**. On a single-replica service, there's nothing to pin to.
* A **running** service. Waking an idle service can change which replica a `session_id` maps to.
* Available on **Enterprise** by default when the feature is GA.
* Supported on standard ClickHouse Cloud services. [BYOC](/docs/cloud/reference/byoc/overview) isn't supported yet.

<h2 id="configuring-replica-aware-routing">
  Configuring replica-aware routing
</h2>

Open a [support](https://clickhouse.com/support/program) ticket and ask to enable HTTP-based sticky replica routing. Include your service ID and why you need it (temporary tables, session state, cache reuse, or read-after-write consistency). After it's enabled, start sending `?session_id=` on HTTPS requests. No restart is required.

<h2 id="http-based-routing">
  HTTP-based routing (session\_id)
</h2>

To pin a workload to a replica, set the `session_id` query parameter on the [HTTPS interface](/docs/interfaces/http). The proxy uses consistent hashing on that value to select a replica, so all requests sharing the same `session_id` go to the same server until the cluster topology changes.

You use your existing service hostname. No special sticky hostnames or DNS changes are required.

```bash theme={null}
echo 'SELECT hostName()' | curl \
  -H 'X-ClickHouse-User: default' \
  -H 'X-ClickHouse-Key: <password>' \
  'https://<host>:8443/?session_id=my-workload-1' -d @-
```

Every request carrying `session_id=my-workload-1` lands on the same replica. A different `session_id` value hashes independently and may land on the same or a different replica. The mapping is consistent, but you don't choose *which* replica a given value maps to.

`session_id` is any string you choose (application name, user id, or workload label). Requests without `session_id` keep normal load balancing.

<h3 id="read-after-write-consistency">
  Read-after-write consistency
</h3>

On a multi-replica service, a write on one replica may not be visible on the others until replication catches up. Send your write with a `session_id`, then reuse that same value on follow-up reads. The proxy routes both to the same replica, so you read your own write even while other replicas are still behind.

This pattern works for workloads that write and then immediately read back the same data, such as interactive applications or ETL jobs that validate inserts before moving on. For broader guarantees across all replicas, you can also set [`select_sequential_consistency`](/docs/operations/settings/settings#select_sequential_consistency) to `1` on ClickHouse Cloud.

Any HTTP client that can add a query parameter works, including `curl`, [clickhouse-connect](/docs/integrations/python), JDBC/ODBC, and others. For `clickhouse-go` (v2), use HTTP mode as noted above.

<h3 id="read-after-write-consistency">
  Read-after-write consistency
</h3>

Use the same `session_id` for a write and its subsequent read queries. Replica-aware routing sends those requests to the same replica, so the reads see the latest write even if the other replicas haven't received it yet. This provides read-after-write consistency for as long as the `session_id` continues to map to the same replica.

<h3 id="check-which-replica">
  Check which replica you hit
</h3>

Run the `SELECT hostName()` example above again with the same `session_id`. You should get the same hostname. A different `session_id` may map to a different replica.

<h2 id="subdomain-based-routing-deprecated">
  Subdomain-based routing (deprecated)
</h2>

<Danger>
  **Deprecated**

  The subdomain-based mechanism is being **deprecated** and will no longer be enabled on new services. It doesn't scale (each sticky endpoint requires its own TLS certificate). Use the [HTTP-based `session_id` method](#http-based-routing) instead. If you already use sticky subdomains, contact [support](https://clickhouse.com/support/program) to enable `session_id` routing. This is a breaking change and will require migration.
</Danger>

Previously, enabling replica-aware routing allowed a wildcard subdomain on top of the service hostname. For a service with the host name `abcxyz123.us-west-2.aws.clickhouse.cloud`, any hostname matching `*.sticky.abcxyz123.us-west-2.aws.clickhouse.cloud` (e.g. `aaa.sticky.abcxyz123.us-west-2.aws.clickhouse.cloud`) was hashed by Envoy to a consistent replica. The original hostname continued to use `LEAST_CONNECTION` load balancing, the default routing algorithm.

<h2 id="limitations-of-replica-aware-routing">
  Limitations of replica-aware routing
</h2>

<h3 id="replica-aware-routing-does-not-guarantee-isolation">
  Stickiness can break during service changes
</h3>

Any disruption to the service changes the routing hash ring. That includes server pod restarts (version upgrade, crash, vertical scaling) and scaling out or in. Requests sharing the same `session_id` may then land on a different server pod. If you rely on temporary tables or session-level settings, be ready to recreate them after a remap.

<h3 id="not-workload-isolation">
  Replica-aware routing isn't workload isolation
</h3>

Sticky routing only controls *which* replica handles a request. That replica may still serve other traffic. For dedicated compute, use [compute-compute separation](/docs/cloud/reference/warehouses).

<h3 id="replica-aware-routing-does-not-work-out-of-the-box-with-private-link">
  Private Link and the deprecated subdomain method
</h3>

HTTP `session_id` routing works with [private networking](/docs/cloud/security/connectivity/private-networking) on your normal service hostname. No extra DNS entries are required.

The deprecated subdomain method doesn't: you must add DNS for the `*.sticky.*` hostname pattern, and incorrect setup can imbalance load across replicas.

<h3 id="replica-aware-routing-requires-http">
  Replica-aware routing requires the HTTP protocol
</h3>

Sticky routing is keyed on the `session_id` query parameter, which only exists on the HTTP/HTTPS interface. The native binary protocol carries no such parameter for the proxy to hash on, so replica-aware routing isn't available over the native protocol. Today, native-protocol clients must move the relevant workload to the HTTP interface to use this feature.

<h2 id="troubleshooting">
  Troubleshooting
</h2>

**Queries still land on different replicas with the same `session_id`**

* Confirm `session_id` is a URL query parameter (`?session_id=...`), not an HTTP header.
* Wait briefly after enablement. It can take under a minute to take effect.
* Check whether the service recently scaled or restarted; remapping is expected after topology changes. Use `SELECT hostName()` to discover the new mapping.
