Dynamic Subgraph Routing
Sometimes you need to route requests to different instances of the same subgraph based on the request properties - maybe for testing new versions, handling different regions, or managing load. Hive Router lets you change where requests go dynamically using simple logic expressions.
This guide shows you practical ways to use dynamic routing in real-world scenarios. For the complete
configuration reference, see
override_subgraph_urls configuration.
How It Works
Dynamic routing uses expressions to decide where to send requests. For each request, the router evaluates your expression and routes to the URL it returns.
What you have access to:
.request- The incoming HTTP request (headers, method, etc.).request.path_params- Path parameters captured by the configuredhttp.graphql_endpointpattern (e.g.tenantfromgraphql_endpoint: /{tenant}/graphql).default- The default URL from your supergraph schema.subgraph.name- The name of the subgraph the URL is being resolved for
Per-subgraph overrides live under subgraphs, keyed by subgraph name. Simple example configuration
that routes based on a runtime condition:
override_subgraph_urls:
subgraphs:
subgraph_name:
url:
expression: |
if .request.headers."x-use-special-instance" == "true" {
"https://special-instance.com/graphql"
} else {
.default # Always provide a fallback
}You can also define a single all override that applies to every subgraph without its own entry,
which is handy when the routing logic is shared across subgraphs:
override_subgraph_urls:
all:
url:
expression: |
if .subgraph.name == "reviews" {
"https://reviews.example.com/graphql"
} else {
.default
}Examples
To illustrate how dynamic routing can be used, here are some common scenarios, along with example configurations.
Canary Deployments
One of the most common use cases for dynamic routing is canary deployment. This pattern allows you to roll out a new version of a subgraph to a small, controlled subset of traffic before releasing it to all users.
override_subgraph_urls:
subgraphs:
products:
url:
expression: |
if .request.headers."x-deploy-track" == "canary" {
"https://products-canary.example.com/graphql"
} else {
.default
}With this configuration, your QA team or CI/CD pipeline can test the new deployment in production by
simply adding the X-Deploy-Track: canary header to their requests, without affecting regular
users.
override_subgraph_urls:
subgraphs:
products:
url:
expression: |
# Route 10% of traffic to canary
if random_int(1, 100) <= 10 {
"https://products-canary.example.com/graphql"
} else {
.default
}Regional Routing
If your application is deployed globally, you likely have subgraph instances in multiple geographic regions. Routing users to the instance closest to them can significantly reduce latency.
override_subgraph_urls:
subgraphs:
reviews:
url:
expression: |
region = .request.headers."x-user-region" || "unknown"
if region == "us-east" {
"https://reviews-us-east.example.com/graphql"
} else if region == "eu-west" {
"https://reviews-eu-west.example.com/graphql"
} else if region == "asia-pacific" {
"https://reviews-ap.example.com/graphql"
} else {
# Default to primary region
.default
}Multi-Tenant Routing with Path Parameters
If your GraphQL endpoint embeds a tenant (or other) identifier in its path, you can capture it with
http.graphql_endpoint and read it from
.request.path_params. Combined with an all override, this routes every subgraph based on the
matched segment:
http:
graphql_endpoint: /{tenant}/graphql
override_subgraph_urls:
all:
url:
expression: |
tenant = string!(.request.path_params.tenant)
replace(string!(.default), "/api/", "/api/" + tenant + "/")A request to /acme/graphql resolves tenant to "acme" before the expression runs.