Apollo Server v4 resolver continues after client disconnect
0 reputation · 24 Oct 2021, 08:58 UTC
0 reputation · 24 Oct 2021, 08:58 UTC
Goal: determine whether Apollo Server v4 automatically halts resolver execution when the client aborts the HTTP request, or whether each resolver must explicitly forward the request abort signal to downstream data sources.
Apollo Server v4 exposes the Node HTTP request in context, so resolvers can read req.signal. Because GraphQL execution cancellation is not specified by the GraphQL spec, abort behavior depends on the Server integration package and Node.js version. AbortSignal.timeout is only available in newer Node.js releases, so combining request cancellation with operation deadlines may require version-specific handling.
req.signal aborts?req.signal to database clients or fetch calls?req.signal with AbortSignal.timeout for an operation-level deadline?34775 reputation · 24 Oct 2021, 18:23 UTC
Apollo Server v4 does not automatically reject or cancel in-flight resolver promises when a client aborts an HTTP request. The GraphQL execution engine continues to process the resolver until the returned Promise resolves or rejects, regardless of the connection state.
To stop downstream work upon a client disconnect, resolvers must manually forward the req.signal (provided via the request object in the context) to the data source. If the signal is not passed to the underlying database client or API call, the server will continue to consume resources until the operation completes naturally.
context.req.signal directly to libraries that support AbortSignal (such as fetch, pg, or mongodb).req.signal.aborted and throw an error to exit the resolver early.To implement an operation-level deadline that triggers regardless of whether the client is still connected, use AbortSignal.any(). This creates a composite signal that aborts if either the client disconnects or the timeout expires.
const timeoutSignal = AbortSignal.timeout(5000); // 5 second deadline
const combinedSignal = AbortSignal.any([context.req.signal, timeoutSignal]);
const data = await fetch('https://api.example.com/data', { signal: combinedSignal });
| Feature | Requirement | Behavior |
|---|---|---|
AbortSignal.any() |
Node.js v20.0.0+ | Triggers on the first signal to abort. |
AbortSignal.timeout() |
Node.js v17.3.0+ | Triggers after the specified milliseconds. |
| Downstream Cancellation | Library Support | Only works if the driver/client explicitly implements AbortSignal. |
To verify this behavior in your environment:
setTimeout wrapped in a Promise that logs "Completed" upon resolution.curl process).fetch call passing req.signal and verify that the promise rejects with an AbortError immediately upon disconnect.Diagnostic Detail: Are you using a custom integration package (e.g., @apollo/server with a specific Express/Fastify wrapper) or a managed hosting environment? Some proxy layers may handle timeouts differently before the signal reaches Node.js.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.