Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ Represents the incoming HTTP request. It exposes nested fields such as:
- `.request.url.host` - the request host (e.g. `api.example.com`).
- `.request.url.port` - the request port (e.g. `443`).
- `.request.url.path` - the request path (e.g. `/graphql`).
- `.request.url_matches` - path parameters captured from `http.graphql_endpoint` patterns (for
example, with `/graphql/{wildcard}`, `.request.url_matches.wildcard` contains the matched value).
- `.request.operation.name` - the name of the GraphQL operation being executed, if provided.
- `.request.operation.type` - the type of GraphQL operation being executed (e.g. `"query"`,
`"mutation"`, or `"subscription"`).
Expand All @@ -79,8 +81,9 @@ not yet exist.

### `.subgraph`

Available in both **request** and **response** header rules. It provides metadata about the subgraph
handling the current request, including:
Available in [dynamic routing expressions](./override_subgraph_urls), **request** header rules, and
**response** header rules. It provides metadata about the subgraph handling the current request,
including:

- `.subgraph.name` - the name of the subgraph as defined in your supergraph schema.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,74 @@
title: "override_subgraph_urls"
---

The `override_subgraph_urls` configuration allows you to dynamically change the URL for a subgraph
at runtime, based on the properties of an incoming request.
The `override_subgraph_urls` configuration allows you to dynamically change subgraph URLs at runtime
based on the incoming request.

This is the primary mechanism for implementing advanced routing patterns. For detailed guides and
use cases, see the [Dynamic Subgraph Routing](/docs/router/guides/dynamic-subgraph-routing) guide.

## Configuration Structure

The `override_subgraph_urls` key is a top-level object in your `router.config.yaml`. The keys within
this object are the names of the subgraphs you wish to override, as they appear in your supergraph
schema.
The `override_subgraph_urls` key is a top-level object in your `router.config.yaml`.
It supports two override scopes:

For each subgraph, you must specify a `url` property.
- `subgraphs`: Per-subgraph URL overrides keyed by subgraph name.
- `all`: A single override expression applied to all subgraphs that do not have a dedicated
override under `subgraphs`.

Per-subgraph overrides always take precedence over `all`.

```yaml
override_subgraph_urls:
# The name of the subgraph to override
products:
url: # ... url definition
reviews:
url: # ... url definition
all:
expression: # ... global expression
subgraphs:
products:
url: # ... url definition
reviews:
url: # ... url definition
```

## Options

### `url`
### `all`

- **Type:** `object`
- **Required:** No

`all.expression` lets you define one routing expression that applies to every subgraph without its
own entry under `subgraphs`.

Within the `expression`, you have access to:

- `.request`: The incoming HTTP request object (headers, parsed operation, and `url_matches`).
- `.default`: The original subgraph URL from the supergraph schema.
- `.subgraph.name`: The name of the subgraph currently being resolved.
Comment thread
ardatan marked this conversation as resolved.

```yaml
override_subgraph_urls:
all:
expression: |
if .subgraph.name == "products" && .request.headers."x-region" == "us-east" {
"https://products-us-east.example.com/graphql"
} else {
.default
}
```

If `http.graphql_endpoint` uses path parameters, they are available under `.request.url_matches`:

```yaml
http:
graphql_endpoint: /graphql/{wildcard}
override_subgraph_urls:
all:
expression: |
segment = string!(.request.url_matches.wildcard)
replace(string!(.default), "/api/", "/api/" + segment + "/")
```

### `subgraphs.<name>.url`

- **Type:** `string` or `object`
- **Required:** Yes
Expand All @@ -42,8 +84,9 @@ is useful for permanently redirecting a subgraph without recomposing your superg

```yaml
override_subgraph_urls:
products:
url: "https://products.staging.svc.cluster.local/"
subgraphs:
products:
url: "https://products.staging.svc.cluster.local/"
```

#### Dynamic URL with `expression`
Expand All @@ -54,20 +97,21 @@ decisions.

- `expression`: **(string, required)** An [expression](./expressions) that computes the new URL.

Within the `expression`, you have access to two key variables:
Within the `expression`, you have access to:

- `.request`: The incoming HTTP request object, including its headers.
- `.default`: The original subgraph URL from the supergraph schema, which should be used as a
fallback.
- `.request`: The incoming HTTP request object (headers, parsed operation, and `url_matches`).
- `.default`: The original subgraph URL from the supergraph schema.
- `.subgraph.name`: The name of the subgraph currently being resolved.

```yaml
override_subgraph_urls:
reviews:
url:
expression: |
if .request.headers."x-region" == "eu" {
"https://reviews.eu.api/graphql"
} else {
.default
}
subgraphs:
reviews:
url:
expression: |
if .request.headers."x-region" == "eu" {
"https://reviews.eu.api/graphql"
} else {
.default
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,21 @@ For each request, the router evaluates your expression and routes to the URL it

- `.request` - The incoming HTTP request (headers, method, etc.)
- `.default` - The default URL from your supergraph schema
- `.subgraph.name` - The current subgraph name

Simple example configuration that routes based on a runtime condition:

```yaml title="router.config.yaml"
override_subgraph_urls:
subgraph_name:
url:
expression: |
if .request.headers."x-use-special-instance" == "true" {
"https://special-instance.com/graphql"
} else {
.default # Always provide a fallback
}
subgraphs:
subgraph_name:
url:
expression: |
if .request.headers."x-use-special-instance" == "true" {
"https://special-instance.com/graphql"
} else {
.default # Always provide a fallback
}
```

## Examples
Expand All @@ -53,14 +55,15 @@ to all users.

```yaml title="router.config.yaml"
override_subgraph_urls:
products:
url:
expression: |
if .request.headers."x-deploy-track" == "canary" {
"https://products-canary.example.com/graphql"
} else {
.default
}
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
Expand All @@ -73,15 +76,16 @@ users.

```yaml title="router.config.yaml"
override_subgraph_urls:
products:
url:
expression: |
# Route 10% of traffic to canary
if random_int(1, 100) <= 10 {
"https://products-canary.example.com/graphql"
} else {
.default
}
subgraphs:
products:
url:
expression: |
# Route 10% of traffic to canary
if random_int(1, 100) <= 10 {
"https://products-canary.example.com/graphql"
} else {
.default
}
```

</Tabs.Tab>
Expand All @@ -95,19 +99,20 @@ regions. Routing users to the instance closest to them can significantly reduce

```yaml title="router.config.yaml"
override_subgraph_urls:
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
}
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
}
```
Loading