diff --git a/docs/docs.json b/docs/docs.json
index 2abfffc7..bc937b7c 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -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",
diff --git a/docs/router/configuration.mdx b/docs/router/configuration.mdx
index 927becd6..3ad6ee95 100644
--- a/docs/router/configuration.mdx
+++ b/docs/router/configuration.mdx
@@ -1855,6 +1855,35 @@ For mor information on how to use the expression language, please refer to the [
| RATE_LIMIT_SIMPLE_PERIOD | period | | The rate limiting period, e.g. "10s", "1m", etc... | 1s |
| RATE_LIMIT_SIMPLE_REJECT_EXCEEDING_REQUESTS | reject_exceeding_requests | | 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 | | 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 | | 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
@@ -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"
diff --git a/docs/router/feature-flags.mdx b/docs/router/feature-flags.mdx
new file mode 100644
index 00000000..c4eeb2bd
--- /dev/null
+++ b/docs/router/feature-flags.mdx
@@ -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.
+
+
+ For a primer on Cosmo feature flags and rollout strategies, see the [concepts guide](/concepts/feature-flags).
+
+
+## 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.
+
+
+ Name feature flag schemas using the `feature-flag_*.graphql` convention and check in an empty placeholder subgraph file to keep composition predictable.
+
+
+## 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.