Forwarding Subgraph Response Extensions
GraphQL subgraphs can attach anextensions object to their responses. By default, the router does not propagate these extensions to the client. When forwarding is enabled, the router merges the top-level keys of the extensions object from every subgraph that participated in the query and returns the merged object on the final response.
This is useful for surfacing metadata such as rate-limit state, auth context, or custom telemetry from subgraphs back to the client without exposing every internal field.
Enabling Extension Forwarding
Add the following to your config.yaml:Allow List
allowed_extension_fields restricts which top-level keys of the extensions object are propagated to the client. Any key not on the list is dropped before the response is sent.
The list applies to the top level only. Nested values inside an allowed field are forwarded as-is.
Conflict Resolution Algorithms
When more than one subgraph returns the same extension field, the router applies the configured algorithm to pick a single value for the merged response. The algorithm operates on top-level keys only and never deep-merges nested values.-
first_write: Keeps the value from the first subgraph that wrote the field. Later writes from other subgraphs to the same field are ignored. This is the default. -
last_write: Keeps the value from the last subgraph that wrote the field. Earlier writes are overwritten.
Example
Configuration:-
employeesreturnsextensions: { "traceId": "abc", "rateLimit": { "remaining": 100 } } -
productsreturnsextensions: { "rateLimit": { "remaining": 50 }, "debug": { "source": "products" } }
traceId came from employees. rateLimit came from employees because first_write keeps the first write. debug was dropped because it is not in the allow list. With algorithm: last_write, rateLimit would instead resolve to { "remaining": 50 } from products.
For an incremental @defer response, the merge spans primary and deferred subgraph fetches. The initial part can contain values collected during primary execution; the part with hasNext: false contains the authoritative cumulative result. first_write and last_write use the request’s actual merge order across all loader phases, and clients should shallow-merge each part’s top-level extensions object.
Subgraph response extensions are merged independently for each client request. State from earlier requests does not leak into later ones.
This is the inverse direction of Forward Client Extensions, which forwards the
extensions object the client sends with the request to each subgraph.