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
1 change: 1 addition & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@
},
"router/compliance-and-data-management",
"router/query-batching",
"router/feature-flags",
"router/subgraph-error-propagation",
"router/file-upload",
"router/access-logs",
Expand Down
40 changes: 39 additions & 1 deletion docs/router/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1855,6 +1855,35 @@ For mor information on how to use the expression language, please refer to the [
| RATE_LIMIT_SIMPLE_PERIOD | period | <Icon icon="square-check" iconType="solid" /> | The rate limiting period, e.g. "10s", "1m", etc... | 1s |
| RATE_LIMIT_SIMPLE_REJECT_EXCEEDING_REQUESTS | reject_exceeding_requests | <Icon icon="square" /> | Reject the complete request if a sub-request exceeds the rate limit. If set to false, partial responses are possible. | false |
| RATE_LIMIT_SIMPLE_HIDE_STATS_FROM_RESPONSE_EXTENSION | hide_stats_from_response_extension | <Icon icon="square" /> | Hide the rate limit stats from the response extension. If the value is true, the rate limit stats are not included in the response extension. | false |
| | overrides | <Icon icon="square" /> | Optional per-key overrides for rate, burst, and period. Keys must match the fully qualified Redis key (prefix + suffix). | |

### Rate Limit Overrides

Overrides let you provide bespoke limits for specific rate-limit keys—for example, to give paying customers higher throughput or to throttle noisy tenants. Each entry in `simple_strategy.overrides` is a map keyed by the full Redis key and can override `rate`, `burst`, and `period`.

Key structure reminder:

- `storage.key_prefix` defines the prefix applied to every key.
- `key_suffix_expression` appends the dynamic portion at runtime.
- An override must include both segments (for example, `cosmo_rate_limit:id_premium_user`).

The example below uses `request.auth.claims.client_id` to build suffixes such as `id_paying_client`, which then match the override keys.

```yaml
rate_limit:
simple_strategy:
overrides:
cosmo_rate_limit:id_premium_user:
rate: 25
burst: 50
period: 1m
cosmo_rate_limit:id_trial_user:
rate: 2
burst: 4
period: 30s
```

Any fields you omit inherit from the base simple strategy configuration. This allows targeted tuning without duplicating the global defaults.

### Rate Limit Error Extension Code

Expand All @@ -1876,13 +1905,22 @@ rate_limit:
reject_exceeding_requests: false
reject_status_code: 200
hide_stats_from_response_extension: false
overrides:
cosmo_rate_limit:id_paying_client:
rate: 20
burst: 40
period: 1m
cosmo_rate_limit:id_trial_client:
rate: 2
burst: 2
period: 30s
storage:
cluster_enabled: false
urls:
- "redis://localhost:6379"
key_prefix: "cosmo_rate_limit"
debug: false
key_suffix_expression: ""
key_suffix_expression: "request.auth.claims.client_id != nil ? 'id_' + request.auth.claims.client_id : ''"
error_extension_code:
enabled: true
code: "RATE_LIMIT_EXCEEDED"
Expand Down
56 changes: 56 additions & 0 deletions docs/router/feature-flags.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: "Feature Flags"
description: "Route traffic through alternate subgraphs by toggling feature flags per request."
icon: flag
sidebarTitle: Feature Flags
---

## Overview

Router-level feature flags let you swap a subgraph at request time without a redeploy. Each flag defines a replacement subgraph. When a request includes the matching header or cookie, the router resolves the target subgraph to the flagged replacement.

<Info>
For a primer on Cosmo feature flags and rollout strategies, see the [concepts guide](/concepts/feature-flags).
</Info>

## Declare a Feature Flag

Add the flag configuration in `router-compose.yaml`. Each flag defines one or more `feature_graphs` that describe the replacement subgraph to serve when the flag is active.

```yaml router-compose.yaml
feature_flags:
- name: test_checkout
feature_graphs:
- name: checkout_canary
subgraph_name: checkout
routing_url: https://api.example.com/checkout-canary/graphql
schema:
file: feature-flag_checkout.graphql
subgraphs:
- name: checkout
routing_url: https://api.example.com/checkout/graphql
schema:
file: checkout.graphql
```

Key points:

- `feature_flags[*].name` is the value you will send from the client (case sensitive).
- `feature_graphs[*].subgraph_name` must match the corresponding entry under `subgraphs` (`checkout` in the example).
- The router swaps the referenced `subgraph_name` with the replacement defined in `feature_graphs` when the flag is active.

<Note>
Name feature flag schemas using the `feature-flag_*.graphql` convention and check in an empty placeholder subgraph file to keep composition predictable.
</Note>

## Trigger the Flag

Activate a flag by sending the header (or matching cookie) with the desired flag name. All requests that include the header are routed through the replacement subgraph.

```http
GET /graphql HTTP/1.1
Host: router.example.com
X-Feature-Flag: test_checkout
```

When the router receives `X-Feature-Flag: test_checkout`, it composes the operation against the replacement schema and forwards traffic to the routing URLs declared in the flag configuration.