GraphQL

Write an awesome doc for GraphQL. A very nice an practical one extracted from GraphQL official documentation.

View on GitHub

Cost Analysis

# When we have a public API we need to take care of:

Threat protection

Make sure that client ain't asking for too much response data. You can find an example of this here

Rate limiting

How many transactions per second per consumer are allowed for each endpoint.

Monetization

Charge customers based on the weight of their API call.

Potential Problem

In GraphQL our client can send a dramatically different kind of transactions. This means that for one query we might be able to process and return a response in less than a second but for another we might crash our entire backend due to workload volume!

[!CAUTION]

It is also possible that client might send a seemingly harmless not deep, not wide, not long query to our GraphQL service but in fact it is very expensive to run.

This brings us to the topic of this doc, we cannot treat all queries the same in GraphQL.

Solution: Calculating Queries’ Cost

By calculating each query’s cost we can:

  1. Prevent extremely heavy queries from being executed (DoS protection).
  2. Limit how many queries with a specific weight can be executed per second per consumer (rate limiting).
  3. And we can charge more for heavy queries compare to light weight queries (monetization).

Cost Analysis Methods

[!NOTE]

Why we have three different kind of cost analysis?

Because we have 3 kind of need;

Why 3 method of cost analysis

  • We need to protect our GraphQL service from DoS attacks, thus we rely on how heavy one query might be.
  • For rate limiting we can:
    • Rely on dynamic query analysis and deduct after execution.
    • Deduct first based on the upper bound and then refund if we’ve deducted too much.
  • For monetization we can rely on dynamic query analysis.
  • When I wrote this doc first I only watched one YouTube video and there he said that since scalar types are already presumably fetched from DB we’re gonna skip them from static query cost analysis. But there are other approaches to this too. Find out more here

Static Query Analysis

[!CAUTION]

It seems depth and complexity* are two different things when it comes to tooling. But in the grand scheme of things the complexity of a query increases with the number of fields AND the depth.

*Query complexity refers to the computational resources needed to fulfill a query.

Learn more about query depth limiting here.

GraphQL Schema https://github.com/kasir-barati/graphql-js-ts/blob/e81e8883a9538af29ea0253849163677dce1fdf2/docs/best-practices/assets/fictional-back-graphql-schema.graphql#L1-L57
Query https://github.com/kasir-barati/graphql-js-ts/blob/9a6c406b6b3d2d952970d0defb1957003ef49034/docs/best-practices/assets/fictional-back-graphql-schema.graphql#L59-L75
Static Query Analysis

Notes:

  • Type cost roughly corresponds to how much data a query might produce.
  • Field cost corresponds to how much work needs to be done fir a query to be processed by our GraphQL service.
  • Note that field cost & type cost are upper bounds and not the actual final costs.
  • We skip scalar types while calculating the cost of a query, but you can include it in case a specific scalar type is costly. E.g. here we do not calculate name as a field in the field counts.
    But keep in mind that this is not the only approach. Find out more here.
  • Learn about @listSize directive here.
Type Counts
Query: 1
Account: 1
TransactionConnection: 1
PageInfo: 1
TransactionEdge: 5
Transaction: 5
Type Cost 14
Field Counts </table> </td> </tr> </table>
All the pictures related to the static query analysis in ascending order
TK: https://youtu.be/_WpM7qylvYg?si=rQFxNNj3CjWGc8Bf ##### Should I calculate scalar type in my cost analysis? According to what I read [here](https://hygraph.com/docs/api-reference/basics/query-complexity) it seems it is a good idea to do so. It says: > - Each scalar field in a query contributes one point to the query complexity. > - Relations/Unions multiply their complexity times the level of nesting in the query. # Ref - https://mmatsa.com/blog/methods-of-cost-analysis. - [Why GraphQL Cost Analysis](https://youtu.be/QZfmSDofeVg?si=w_5lZDHlJ9LUZCRE). - [Methods of GraphQL Cost Analysis](https://youtu.be/EfRjeZxQFio?si=mGQyrLSypTyf4dWJ). - [GraphQL Static Query Analysis Example](https://youtu.be/DkHNZOA3rM0?si=GnUEeYoCQyshI2n0). - [APIDays Interface 2021 - Securing GraphQL with Cost Directives](https://youtu.be/_WpM7qylvYg?si=rQFxNNj3CjWGc8Bf).
Query.account: 1 </td> </tr>
Account.transactions: 1 </td> </tr>
TransactionConnection.pageInfo: 1 </td> </tr>
TransactionConnection.edges: 1 </td> </tr>
TransactionEdge.node: 5 </td> </tr> </table> </td> </tr>
Field Cost 9