Use case
Apollo Server added incremental delivery support for @defer/@stream in #8148, but this only works for the direct execution path (executeIncrementally). The gateway executor path (internals.gatewayExecutor) always wraps the result as { singleResult: result }, which means incremental delivery results from a gateway are silently ignored.
When using @apollo/gateway or any custom GatewayExecutor implementation that supports @defer, the incremental results cannot flow through to the client because:
GatewayExecutionResult is typed as plain ExecutionResult — gateways can't return incremental results
requestPipeline.ts doesn't check for initialResult/subsequentResults in the gateway branch
Proposed change
The runtime fix in requestPipeline.ts is small — check if the gateway result contains initialResult and route it through the existing formatErrorsInSubsequentResults handlers, matching the pattern in the direct execution branch:
// packages/server/src/requestPipeline.ts
} else if (internals.gatewayExecutor) {
const result = await internals.gatewayExecutor(
makeGatewayGraphQLRequestContext(requestContext, server, internals),
);
if ('initialResult' in result) {
return {
initialResult: result.initialResult,
subsequentResults:
'pending' in result.initialResult
? formatErrorsInSubsequentResultsAlpha9(
result.subsequentResults as
AsyncIterable<GraphQLExperimentalSubsequentIncrementalExecutionResultAlpha9>,
)
: formatErrorsInSubsequentResultsAlpha2(
result.subsequentResults,
),
};
} else {
return { singleResult: result };
}
The part I'm less sure about is how to best define the incremental delivery types in @apollo/server-gateway-interface. GatewayExecutionResult needs to become a union that includes incremental result types (both Alpha2 and Alpha9), but there are different approaches for how detailed those type definitions should be. I have a working prototype that mirrors the incrementalDeliveryPolyfill.ts structure, but I'd welcome input on the preferred approach.
I have a prototype with tests on my fork:
https://github.com/Re-cool/apollo-server/tree/feat/gateway-incremental-delivery
Use case
Apollo Server added incremental delivery support for
@defer/@streamin #8148, but this only works for the direct execution path (executeIncrementally). The gateway executor path (internals.gatewayExecutor) always wraps the result as{ singleResult: result }, which means incremental delivery results from a gateway are silently ignored.When using
@apollo/gatewayor any customGatewayExecutorimplementation that supports@defer, the incremental results cannot flow through to the client because:GatewayExecutionResultis typed as plainExecutionResult— gateways can't return incremental resultsrequestPipeline.tsdoesn't check forinitialResult/subsequentResultsin the gateway branchProposed change
The runtime fix in
requestPipeline.tsis small — check if the gateway result containsinitialResultand route it through the existingformatErrorsInSubsequentResultshandlers, matching the pattern in the direct execution branch:The part I'm less sure about is how to best define the incremental delivery types in
@apollo/server-gateway-interface.GatewayExecutionResultneeds to become a union that includes incremental result types (both Alpha2 and Alpha9), but there are different approaches for how detailed those type definitions should be. I have a working prototype that mirrors theincrementalDeliveryPolyfill.tsstructure, but I'd welcome input on the preferred approach.I have a prototype with tests on my fork:
https://github.com/Re-cool/apollo-server/tree/feat/gateway-incremental-delivery