Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Traversing the GraphQL AST and Calculating Query Costs

September 13, 2023

Traversing the GraphQL AST and Calculating Query Costs

GraphQL Tokkyo LT


September 13, 2023

More Decks by joe_re

Other Decks in Technology


  1. About me ▸ X: @joe_re ▸ GitHub: @joe-re ▸ Tech

    Lead at CureApp Inc. ▸ One of the organizer of GraphQL Tokyo
  2. What are I am talking about today ▸ How GraphQL

    rate limiting differs from REST API ▸ Walking through the GraphQL AST by using graphql-js ▸ Introduce three examples to walk through GraphQL API based on actual use cases from graphql-cost-calculator NOTE: 
 1. I believe the basic concept is not signi fi cantly different from other languages. However, this assumes NodeJS environment, as I'm not familiar with GraphQL tooling in other languages. 
 2. There’s some other libraries to provide a way to calculate a GraphQL cost but I am not talking about them today.
  3. The GraphQL API rate limiting is different from REST API’s

    ▸ We can’t simply count the number of queries for GraphQL rate limiting because GraphQL query can replace multiple REST API calls. ▸ Small queries only consume minimal server resources, but a single complex GraphQL query could be equivalent to thousands of REST API calls. ▸ Until the server executes actual GraphQL calls, we can’t determine their true cost.
  4. Static analysis is important for blocking queries before they are

    executed ▸ It’s the popular way to calculate GraphQL queries cost to use rate limit instead of counting number of requests call. ▸ This should be done statically by analyzing the query's AST before execution. ▸ Because if some huge queries are executed once, it could consume huge server resources.
  5. A rate limiting score on GitHub GraphQL API Refer: https://docs.github.com/en/graphql/overview/resource-limitations

    3. Although we're returning 60 labels, the API has to connect to each of the 5,000 potential total issues to get the list of labels. So, requests for labels = 5,000 2. Although we're returning 50 issues, the API has to connect to each of the 100 repositories to get the list of issues. So, requests for issues 
 = 100 4. Total = 5,101 1. Although we're returning 100 repositories, the API has to connect to the viewer's account once to get the list of repositories. So, requests for repositories = 1 5. Dividing by 100 and rounding gives us the fi nal score of the query: 51
  6. graphql-cost-calculaor ▸ It walks through GraphQL queries AST and estimate

    a cost statically. ▸ This library offers means to calculate the cost of query, facilitating rate limiting similar to the GiHub GraphQL API. ▸ https://github.com/joe-re/graphql-cost-calculator
  7. GraphQL queries AST Root is OperationDe fi nition. (Query/Mutation/Subscription) Each

    fi elds have “kind” property to provide own node type
  8. Using visitor pattern to walk through an AST ▸ Refer:

    https://graphql.org/graphql-js/language/#visitor ▸ graphql-js offers a visitor pattern for traversing the GraphQL AST through the visit function ▸ With the visit function, you can use the enter/leave 
 steps to traverse the AST. ▸ By specifying named visitors, 
 you can target and traverse speci fi c kinds of nodes.
  9. Three examples to introduce how to walk through GraphQL AST

    ▸ I will introduce three use cases that explain how to walk through a GraphQL AST. ▸ 1. Counting requests for each unique connection 
 2: Resolving Fragment 
 3: Identifying Object Type ▸ Each example is based on an actual use case from the library, but it has been simpli fi ed for easy understanding.
  10. Example1: Counting requests for each unique connection 1. When it

    enters SelectionSet, get fi rst/last from arguments 2. If it has a fi rst/last argument, the multiplier is incremented and pushed to the stack 3. If it lacks a fi rst/last argument, 
 the current multiplier value is pushed to the stack. 4. If it’s a connection node, calculates a cost based on current multiplier 5. When it leaves SelectionSet, 
 the current multiplier value is reduced from the stack.
  11. Example2: Resolving Fragment 1. First, store all fragment de fi

    nitions. 2. Upon encountering a FragmentSpread, it is replaced with the fragment de fi nition stored in the fi rst step.
  12. Example3: Identifying Object Type 1. Retrieve the parent type because

    a parent know what type is for each fi eld. 
 While the AST doesn't recognize the actual fi eld type, the GraphQL Schema does. With this combination, you can obtain the actual type name. 2. Obtain the node's fi eld class from the schema. 
 This class includes a `.type` attribute that provides the actual type name of the fi eld.
  13. In conclusion ▸ It’s easy to walk through GraphQL AST

    more than you thought. ▸ And it’s really fun. 😉 ▸ Thanks for listening. 🙏