Proxy · Forward client extensions

GraphQL Extensions Forwarding - Queries, Mutations, and Subscriptions

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

No configuration needed. Works for queries, mutations, and subscriptions.

Request payload

JSON bodyqueryvariablesextensionsCosmo RouterpassthroughSubgraphreads extensions

Available onFreeProEnterprise

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.

Default-on passthrough: customize only when you need to.

Forward client extensions

Before & After

Before CosmoWith Cosmo
Custom endpoints or envelope formats for extra dataStandard GraphQL `extensions` field
No way to attach per-subscription auth tokens`extensions` in the subscription payload carries them
Structured data encoded awkwardly into headersJSON structure preserved end-to-end
Non-standard workarounds every client has to learnSpec-compliant, works with libraries that support extensions

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.

How extensions forwarding works

01
HTTP body and WS message payloads.

Client sends extensions

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

02
No opt-in flag.

Router receives the payload

The `extensions` field is preserved as received.

03
Same structure end to end.

Extensions travel downstream

Extensions travel with every subgraph call on outgoing requests.

04
Additive metadata.

Subgraphs consume what they need

Each subgraph reads the fields it cares about and ignores the rest.

Use cases

Patterns teams use first

Auth tokens, feature flags, and client metadata: same field, different payloads.

Standards compliant

Spec

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

Subscription support

WebSocket

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

JSON

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

Pass extensions through Cosmo Router

Default forwarding for queries, mutations, and subscriptions. See the docs for response extensions.

FAQ

Forward client extensions

More detail in the forward client extensions documentation.