# GraphQL Extensions Forwarding - Queries, Mutations, and Subscriptions

Use the `extensions` field to send extra data from clients to subgraphs without stuffing it into headers.

## The problem

### Structured context should not live in headers
Headers flatten everything. Subscriptions cannot vary headers per operation. The GraphQL spec already has a place for extra JSON: use it.

### Headers are a poor fit for structured data
HTTP headers are flat strings. Sending `{"features":{"newCheckout":true,"betaSearch":false}}` through a header means encoding JSON as a string and decoding it everywhere it lands.

### WebSocket subscriptions have no per-operation headers
A WebSocket connection is established once. After that, every subscription operation flows over the same socket. There is no way to attach a different `Authorization` header to operation #2 vs. operation #1.

### Custom workarounds fragment the API
Teams invent sidecar endpoints, bespoke envelope formats, or hidden query arguments to work around the header limitation. None of that is standard.

## Our solution

### Pass any JSON context from clients to subgraphs, including subscriptions
The GraphQL `extensions` object is the spec-backed place for structured client context. Cosmo Router forwards it to subgraphs by default—queries, mutations, and subscriptions—without a feature flag or a custom side channel.

### What happens at request time
1. The router attaches the client's `extensions` object to each outgoing subgraph request, so structured payloads stay JSON-shaped end to end for queries, mutations, and subscriptions.
2. GraphQL over HTTP defines `extensions` as a JSON object next to `query` and `variables`. Clients put whatever structured data they need there, and the router forwards it untouched to every subgraph involved in the operation.
3. For `graphql-ws` subscriptions, `extensions` lives in the subscription message payload—the reliable way to attach per-operation data on a shared WebSocket. No configuration; it works by default.
4. Subgraphs read the fields they care about; the router does not reshape or flatten the JSON.

## Behavior
### Technical behavior
- Forwarding is automatic for queries and mutations over HTTP.
- For subscriptions, requires a `graphql-ws` compatible setup on both router and subgraph.
- The JSON structure is preserved exactly; the router does not reshape or flatten it.
- Subgraphs must be designed to read and act on the fields they expect. The router does not validate the contents.
- No configuration required, enabled by default.

## Use cases

### Patterns teams use first
Auth tokens, feature flags, and client metadata: same field, different payloads.

### Standards compliant
Implements the `extensions` field as defined in the GraphQL over HTTP specification. Works with any GraphQL client library that supports it.

### Subscription support
The reliable way to send per-subscription initialization data. WebSocket connections are established once; `extensions` in the subscription payload carries per-operation tokens after that.

### Flexible data structure
Send any JSON object (auth tokens, feature flags, client metadata) without encoding it into a flat header string.

## How extensions forwarding works

### Client sends extensions
Structured context lives in the JSON body under the `extensions` field—not squeezed into header strings—including `graphql-ws` subscription payloads.

### Router receives the payload
The `extensions` field is preserved as received.

### Extensions travel downstream
Extensions travel with every subgraph call on outgoing requests.

### Subgraphs consume what they need
Each subgraph reads the fields it cares about and ignores the rest.
