federation
federation copied to clipboard
Custom GraphQL Executor Option
Add ability to configure a custom GraphQL executor for the Apollo Gateway that would be used here: https://github.com/apollographql/federation/blob/main/gateway-js/src/executeQueryPlan.ts#L103
This would be similar to the configuration option in Apollo Server to override the GraphQL executor: https://github.com/apollographql/apollo-server/blob/main/packages/apollo-server-core/src/graphqlOptions.ts#L53.
howdy @HishamAli81! Thanks for creating this issue. Would you mind expanding on what you'd use this for?
To add some detail, that particular use of executor
is a bit of a shortcut to maintain spec compliance, resolving aliases, etc (basically offloading what graphql-js
is already good at). I'll note that the comment above the line using execute
mentions we'd rather prefer to do things differently https://github.com/apollographql/federation/blob/4d45d92e6038933d4bfb2b80439cd5b08ec64700/gateway-js/src/executeQueryPlan.ts#L97-L100
@benweatherman Thanks for the quick reply!
Just as that comment suggests, running graphql.execute()
may be a necessary evil, but is a pretty heavy handed way to maintain spec compliance.
I agree that there are probably better ways to handle this differently and not have to run graphql.execute()
at all - do you know if there is anything on the roadmap to refactor executeQueryPlan()
to do that? I'd note that the FIXME comment has been in the codebase for 3+ years.
I've previously overridden the Apollo Server executor to customize it to use graphql-jit, similar to the implementation in the graphql-benchmark sample here: https://github.com/benawad/node-graphql-benchmarks/blob/master/benchmarks/apollo-server-fastify%2Bgraphql-jit.js, and have found significant performance gains.
And from initial benchmarking, I've been able to increase throughput by about 70% - 90% (depending on response size) by patching the Apollo Gateway executeQueryPlan()
function to use graphql-jit.
Exposing the option to customize the executor in Apollo Gateway would provide feature parity with Apollo Server, and in the meantime provide some quick performance wins until the FIXME comment is addressed.
Thanks again @HishamAli81 for raising this issue. It's brought up a lot of good discussion internally about how to improve the gateway. At this time, we don't plan to add support for a custom executor.
The motivation for not supporting a custom executor is that it makes it tougher for our future selves:
- We want the ability to improve the executor in the future including replacing it completely. I realize this seems a little dubious, given the FIXME has been in the code for 3 years.
- We don't want to add features that will prevent users from upgrading to the router in the future. There's concern users would rely on subtle differences in executors that could not be ported to the router ecosystem.
- We worry that supporting non-spec-compliant executors will make users distrust Apollo because they'll assume it's an issue with the Apollo Gateway, not custom executors.
The recommendation for improving performance is to use the Apollo Router https://github.com/apollographql/router. I realize it's potentially a pretty unsavory suggestion to use a completely different app, it really is the best way to increase performance without playing whack-a-mole with various JS bottlenecks.
TL;DR the best suggestion at this time is to use the Apollo Router https://github.com/apollographql/router
@benweatherman Thanks again for taking the time to review the request! 😄
Apollo Router is certainly a valid option that will solve a lot of these concerns, and is on the Q4 roadmap for the company I work for. So at least in my case, it's not the most unsavory recommendation.
Although I must say I'm not sure I fully agree with point #3 since the ask is just for Apollo Gateway to provide the ability to users to be able to define our own custom executors, which is a feature that Apollo Server currently supports (https://github.com/apollographql/apollo-server/blob/main/packages/apollo-server-core/src/graphqlOptions.ts#L53).
But I do understand and concede on points #1 and #2 for not supporting custom executors within Apollo Gateway.
As I mentioned previously, I do agree that having to call graphql. execute()
is overkill in the first place and I think there's other ways to implement executeQueryPlan()
without having to call it. I do still think it's worthwhile to invest in improving Apollo Gateway (point #1) especially for those of use where migrating to Apollo Router may not be as straight forward.
I guess all I'm trying to say that I'm willing to lend my hand in support of improving Apollo Gateway. I certainly have my ideas, but would love to pair with someone on your team to hear about thoughts on how best to improve executeQueryPlan()
. Feel free to reach out.
Cheers!
Thanks for the offer of lending a hand @HishamAli81! We aren't likely to spend any time explicitly on executeQueryPlan
in the next few months at least. There may be some tangential work that causes some changes. If we do start to work on optimizing this code, we'll definitely reach out to collaborate. We'd also welcome any thoughts or code you'd be willing to volunteer.