What I learnt about GraphQL
I have been playing around quite a bit with GraphQL, and I thought I would write some notes for anyone to refer for a crash course once you are settled with its basics. (This is not a tutorial/article but just a gist of all that I learnt).
- GraphQL mainly focuses on business entities rather than the technical implementations
- The flow of information is top to bottom i.e. from the Root Node in the schema to the Child Node (Information in the parent can be accessed in the child)
- GraphQL is protocol independent and it can be used to communicate in any protocol (REST, Websockets, WebRTC or anything you can think of).
- Since GraphQL is protocol independent, it is better to make authentication also protocol independent (eg. You can pass JWT tokens as arguments to your GraphQL queries)
- Since nested GraphQL queries can be very costly and can eat up a lot of resources, it is better to use cost analysis libraries to find the cost of the query and limit it or pre-define and whitelist queries on the server side
- Dataloader can be used in conjunction with GraphQL as a temporary cache to avoid going to the database again and again for the same set of records saving a lot of resources.
- All queries in the same level of the GraphQL schema hierarchy are fired in parallel and nested queries are fired sequentially. This saves a lot of time.
- If a field is not queried in the GraphQL query, the respective resolver function of the field is not run saving a lot of time and resource.
- If you want to know the structure of the schema, you can run introspection queries to understand the schema, its attributes, types, parameters, etc.
- GraphQL queries have to be parsed to JSON and converted to an AST (Abstract Syntax Tree) using the available library since native GraphQL queries don’t fit into any data structure except string and hence may be difficult to parse or process programatically.
- GraphiQL gets its schema docs and query suggestions by running introspection queries (The entire GraphQL schema is fetched as a single JSON and used to provide such functionality). The same schema is also used to do validations on the client side to see if a query is valid or not.
- GraphQL is a specification and not an implementation. There are a lot of client and server side libraries for implementing GraphQL.
- The GraphQL output has a similar structure to the GraphQL input and dynamically changes its structure unlike REST APIs where the response structure is same always.
- Client side caching in GraphQL can be implemented using libraries like Relay and Server side caching can be implemented by storing frequently run queries with generated IDs and their result sets in the database/cache.
- We can paginate in GraphQL like we paginate in REST APIs passing the start and limit as arguments, passing page nos. or passing timestamp and ultimately forming respective queries for the result set as needed.
- We can use directives to do run-time operations like skipping or including attributes based on conditions or even write custom directives to get things done at run-time.
- We can use variables to pass changing values to GraphQL arguments and fragments to reuse portions of queries instead of writing them again and again, and aliases let us rename fields as we like.
- GraphQL mutations always run in a sequence unlike GraphQL queries which can either run in series or parallel depending on the hierarchy level.
- GraphQL has a basic set of Types which can be found here using which we can build our own custom types having its own properties (like a class).
- We can define separate Types, its attributes and related entities and then use Schema Stitching to bring relations to each other in the schema.
- Authorization is best handled in the business logic layer where we handle resolver functions (We can resolve after checking if the scopes of the user satisfies the requirements to run the resolver). This way, if the user is not authorized, the relevant query is not run.
- Custom filters for data are handled in resolver functions where the query is formed dynamically based on the values being passed to a filter or array of filters.
- Apart from Queries & Mutations, GraphQL can also handle subscriptions where resolvers and queries can be run every time there is an event and send the response to a pub-sub system.
- A possible GraphQL project structure is to have the schema defined in multiple .graphql files (read and parsed by the server while starting), resolvers in separate files and database connections/dataloader functions in separate files. Depending on the size of the project, you can either separate them into schema, resolvers and db or group them by business functions and put the relevant .graphql file, the resolver and the dataloader file together in respective folders.
- You can secure /graphql data endpoint via an API gateway and have GraphiQL interact with the endpoint securely by using the passHeader option when calling the graphiql endpoint thus allowing for token based security when calling the data endpoint for fetching the schema through the introspection query in addition to having a JWT token as an argument in the GraphQL query.
To help in our journey, there are lot of powerful tools available in the community like Prisma which helps you to add GraphQL on top of your existing SQL based databases, GraphQL Voyager which lets you view your schema as an interactive graph and lots more.
Does not suffice? You can find awesome graphql by Chen-Tsu Lin at https://github.com/chentsulin/awesome-graphql
Like this article? Follow me to get updated on any new articles I would be writing and leave your feedback, suggestions and questions in the comments. See you in my next blog.