Why do I use GraphQL? Also, the case for not using GraphQL.
You must have seen the previous post where I waxed eloquent about how I mess up my Rest APIs. There was no way I would be satisfied doing that to a single technology stack.
Ergo, GraphQL.
What is the need for GraphQL?
Google GraphQL and refer docs- there are smarter people with better answers than me.
But, since the Internet can be a scary place and I love to write about things that I am not an expert in - here’s a gist about what I think.
Back to the story..
GraphQL is the SQL for APIs.
Before you say .. ‘ah.. I now know everything!’, read on.
You see - most of the transactions on the web involve fetching some data or the other.
Clients need to be authenticated, authorised and then request data for those transactions to happen. Servers, which supply the data, will comply with client requests based on pre-defined rules.
Rest is an architectural style that allows you to standardize and streamline client-server requests. You can control resources (accounts, contacts etc.) and the operations (GET, STORE etc.).
So far so good. You may even think that you reached a Nirvana state with what has been described so far, but imagine what would happen if you start a series of requests -
You: Give me contacts
Server: Here are 100 contacts with 501 fields per contact
You: Give me contacts and activities for each contact
Server: Here are 1000 contacts and 1 million activities per contact
You: Give me contact detail
Server: Here you go - 1000 fields of the contact
You: Give me address for same contact
Server: Oh God, you again? Here's the address. And, can you please stop this madness?
You will see such examples in the real world - the problems described are referred as ‘over-fetching’ (getting more data than I need) and ‘under-fetching’ (getting less data than I need).
The properties of over-fetching -
- server fetches more data from database (or may query for related entities that are not always required)
- more data is pushed through the pipe
- client gets more data than required and has to process data to selectively pick and display data.
And, those for under-fetching -
- client does not require all data in one-go, requests for related entities or fields
- additional network requests and more needless traffic
- more time to render UI with complete data
The back & forth between server and client frustrates the server - as seen in above conversation, and more importantly, impacts client-side performance.
The multiple back and forth requests make Rest “chatty”.
Ergo, GraphQL.
(I assure you - Matrix has very little to do with me using ‘ergo’ all the time.)
Really, why do I use GraphQL?
I certainly do not use GraphQL because it -
- is the in-thing in web development today
- is revered by everyone who say there is nothing more wonderful
- is typed, and that makes it so magical
- provides a really good looking IDE that makes it so easy to develop the queries
- makes services so easy to code (all it needs is a gesture and all the little thingies arrange themselves in perfect harmony)
- drastically reduces chatty network traffic and improves the speed to ‘burn rubber’ levels even before ignition is turned on
- uses in-built security rules that makes it so easy to provide role-based authorization
- is loved equally by server and client tech stacks
- specifies a good abstraction layer for databases
- has subscriptions and those are so so amazing
- is developed by Facebook. I happen to adore Zuckerberg
Or, I may be using GraphQL for a couple of points mentioned above and that is embarrassing to admit (or downright stupid).
The primary reasons for me to use GraphQL are -
- it reduces work on the server-side (surprise, surprise!?). I do not have to write APIs for each and every request, or over-engineer APIs imagining all possible scenarios. Since most of my services are data-heavy, I particularly like the fact that I don’t need to maintain a dozen end-points
- development iterations are easier on client. I can make adjustments to client code to fetch more or less data
- pass only the required data b/w client and server
But, on the other hand -
- GraphQL makes it harder to code server-side services (that is just me, not the fault of GraphQL per se).
- I also find it harder to control the queries that clients request while they snicker in the background (the developers of the said client, not client-users. Since I am the only developer in many of my applications, I snicker to myself about myself. I need help!).
I find it easier to just enable standard Rest pattern to start with (scaffolded most of the time). Then, I start enabling GraphQL services for specific transactions and go from there.
Err.. what are you even talking about?
Let’s see a few examples.
If I need to get a specific contact, I would do the following transaction in REST -
GET https://api.com/contact
The response will be -
|
|
I can do the following in GraphQL and send it as a POST request to server -
|
|
The response will be like so -
|
|
The responses in the two transactions speak for themselves!
What are GraphQL operations? And, why should I care?
No matter what we do in the client-server world - we are trying to do one simple thing -
Share data and business logic b/w server and client
One can query, insert, update or delete data and can initiate those transactions from client. This can either happen -
- with the server not caring about the “state” of the client. i.e., client sends request (with authentication incl. as part of request if required), and server answers the call
- server keeps client interests in mind, has an open channel with the client, and keeps track of data so that clients get changes as they happen
GraphQL builds a layer on top of a database to assist you to transmit data in both cases.
Query
GraphQL queries help you to fetch only the records and attributes you need - we have seen examples earlier.
You can also include different entities (think ‘tables’ as an analogy) in the request. Use GraphQL to fetch records with specified relationships, rather than making separate requests for distinct entities.
Mutation
GraphQL mutations are used to insert/change data.
|
|
The above query provides instruction to use a mutation called createContact
that in turn uses addContact
to add a contact record with name Joe
and age 100
.
Subscription
Subscriptions establish a channel between server and client. Clients can subscribe to record updates and get notified (through a simple notification, or by actual ‘push’ of the data from server) whenever there are changes.
Subscriptions use ‘web sockets’ under the hood. This is a battle-tested piece of technology that enables real-time data updates to client.
For example - clients can use the below subscription to get the list of contacts who won the lottery.
|
|
Let’s see the flow -
- Clients subscribe to contacts
- One or more of the contacts get updated in the database when they win lottery
- On database update, a notification gets triggered to clients
- The notification contains contact’s name and deals associated with contact
- Client can thereon show a popup with contact name and show flying balloons for effect
What are the different components required to implement GraphQL?
GraphQL is just the language for API and runtime for executing them queries. It is not hardwired to database and does not specify how the database operations need to be executed.
The different components that implement GraphQL stack are below. These components are not part of GraphQL specifications but are just part of the stack that support transactions using GraphQL.
Server
The implementation/tech stack decides how GraphQL is incorporated in the transaction. Server receives GraphQL requests from clients, establishes connection to database, converts graph queries to a language understood by database, fetches results and sends the responses back to clients.
A server may also include the functions expected from a “normal” server -
- apply business logic to data
- listen to supported types of requests on specified network ports
- takes care of all the supporting infrastructure required to serve requests to clients.
Database
Stores data and maintains atomicity, consistency etc. etc. for data. It is a glorified file system that supports individual transactions and does not mess up the data just because the network went kaput, or your client decided to play a game.
Client
Can be a browser, mobile app or anything that requests data from server and consumes server response to do “something”. We create GraphQL queries, mutations etc. and send them over in a simple POST request.
What are the terms that I should be familiar about?
Schema
A schema is the building block of GraphQL. It is described using a language that we can understand - it can be any language, but a simple option aptly named “Schema Definition Language” is used in the standard implementation.
Consider the below example -
|
|
The schema definition helps a client-side developer to see and understand the relationships b/w data entities, and thereon construct a GraphQL query.
Resolvers
A resolver is a function that returns data in the shape specified by schema.
For e.g. -
|
|
We use a resolver to write queries, mutations and subscriptions.
Object type / fields
In the GraphQL query outlined above -
- Object type is ‘Contact’ and ‘Deal’
- Fields are
name
,description
, andvalue
This is so cool that I slept through the article. Give it to me straight - should I use GraphQL?
Not everywhere.
Use GraphQL when you need to fetch a lot of data having varying shapes / many relationships. Use GraphQL to simplify the data passed between client and server.
At the same time -
- Remember that plain Rest API implementations are simpler
- Even in data-heavy applications, I do not see a big advantage of applying GraphQL everywhere (except architectural uniformity/ standardization, maybe). For e.g. if you have narrow relationships between entities that do not require related data views all the time
- Keep track of how clients use GraphQL - crazy queries can lead to performance issues
Why do I find Rest services simpler?
- Endpoint setup is simple on the server. Expose an API or two, and use an ORM to fetch/update data in one or two steps - no sight of fields and related entities anywhere unless you want to deal with them
- In addition to the previous point, or supplementing it, is the fact that the tooling is amazing - the technology is so old and supported so well that most of the time it just requires a couple of clicks (or lines of code) to fully set up
- I control queries in the back-end - easier control on who accesses the data and how. I also find it easier to solve potential performance issues since I control filters and sort on the server
- But all said and done, I may be finding Rest easier since I have spent so much time with it :)
Ok, I am in. Where should I start?
I find the following technology stacks easy to follow and useful to learn for the long run. The recommendations are skewed towards Vue since I use Vue all the time and strongly believe that Vue is easier on beginners.
Enable GraphQL server-side
It is a good idea to create a server on your own and see GraphQL flow in the back-end for real.
Category | Recommended | Remarks |
---|---|---|
I know SQL and understand DBs | PostGraphile | Refer this |
I want to learn more of serverless | AppSync | Sign up for 1-year limited free servers on Amazon AppSync |
I want to learn GraphQL using a CMS | StrapiJS | In beta, but good for production |
I want to experiment with static sites + GraphQL | Gridsome | New, but promising. |
I know PHP | Laravel + Lighthouse | |
I am looking forward to a long-term relationship | NestJS | Good server capabilities + good GraphQL support |
I am a master | Guide me towards enlightenment, maybe | What are you even doing here? |
Use GraphQL on the client
- Vue + Vue-Apollo
- Svelte + Apollo.
Also see: create a simple to-do with Svelte + GraphQL
Finis
It ends here :)