fields, can possibly be resolved by `n` services •Nested fields may need to be resolved outside the current service •Resolution logic is extremely complex (Avoiding N+1's, handling failure scenarios within resolution of a query, etc) GraphQL
Query { search(query: String!): [SearchResult!] } union SearchResult = User | Issue type Query { user(id: ID!): User } type Query { issue(id: ID!): Issue } type Issue { owner: User! } Schema Stitching The Harder Parts
Service Monolith User Service type Query { search(query: String!): [SearchResult!] } union SearchResult = User | Issue type Query { user(id: ID!): User } type Query { issue(id: ID!): Issue } type Issue { owner: User! }
Jacobson The better approach for handling API design [...] is to create true separation of concerns, rather than have all server-side decisions made by the API provider.
in middleware [...] Vendors in the highly competitive API gateway market are continuing this trend by adding features through which they attempt to differentiate their products. This results in OVERAMBITIOUS API GATEWAY products whose functionality — on top of what is essentially a reverse proxy — encourages designs that continue to be difficult to test and deploy. https://www.thoughtworks.com/radar/platforms/overambitious-api-gateways GraphQL Conf 2019 @__xuorig__
API according to how your services are split up. •Dynamic / runtime "stitching" is scary, proceed with care. •Consider statically building a gateway from a distributed schema using tooling as a middle of the road approach.
to do the wrong thing. •Thinest layer achievable •The API Gateway is "just" another service. •If distributed schemas are necessary, make it easy to "import" them into the gateway. •However, the gateway schema is its own thing that represents the source of truth for our exposed API. It requires •Resolution is done through your service communication of choice.