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 the 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 & forth requests make Rest "chatty".
Ergo, GraphQL.
(I assure you - Matrix has very little to do with me using 'ergo' all the time.)
But 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 -
data: {
contacts: [
{
planet: "earth",
name: "Rama",
age: 42
},
{
planet: "mercury",
name: "Kris",
age: 21
},
{
planet: "mars",
name: "Joe",
age: 63
}
];
}
I can do the following in GraphQL and send it as a POST request to server -
query {
contacts(name: "Rama") {
name
age
}
}
The response will be like so -
data: {
contacts: [
{
name: "Rama",
age: 42
}
];
}
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.
mutation createContact {
addContact(name: "Joe", age: 100) {
id
}
}
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.
subscription listenWonLottery {
wonLottery {
name
deals
}
}
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 -
type Contact {
name: String
deal: Deal
}
type Deal {
description: String
value: String
}
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. -
const resolvers = {
Query: {
contact(root, args) {
return contacts.filter(contact => contact.id === args.id)[0];
},
deals(root, args) {
return deals.filter(deal => deal.id === args.id)[0];
}
},
Contact: {
deals: contact => {
return deals.filter(deal => deal.contactId === contact.id);
}
}
};
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 |
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 :)
Top comments (9)
Thanks for the article.
How are you defining data-heavy applications? Is it an application that is receiving/processing/sending millions of data points per second or is it actually the one with a highly normalized database schema?
That's a good question.
I am referring to high no. of data points = high no. of fields / highly normalized schema.
Sorry for not being clear.
Thanks for clearing out.
It would be great if you can elaborate on the following point as well:
I intended to recommend GraphQL for databases that have many fields and/or relationships.
"..
Since most of my services are data-heavy, I particularly like the fact that I don't need to maintain a dozen end-points".
GraphQL enables selective retrieval and that (for me) is a big plus.
Obviously I am not a good communicator :p
I would like to answer your second question in more detail and have updated the post!
Thanks for the great questions.
I don't know why everybody thinks that Graphql can only be used in case of web development API. There can be more useful things you can do with Graphql. One of the things that I see is that it's a "query language" like SQL. You can query a big amount of data just like SQL does on a large database. Consider this, suppose you have a json data of about 13M lines,what would you do with that? Well, use Graphql and seperate the necessary data out, and apply Machine learning to that data!
Agreed. We will see more such applications as the tooling support becomes more prevalent.
Аnother useless writeup for Graphql.. I mean I had to learn it recently. And it is overenginered too complex and tries to do something js is not good and not supposed to do. In rest api I can open a route to give you your contract by id and it is easy.
While in graphql I have to write schema! then I have to write types. Then I have to write the actual query. Not to mention I have to hack it a bit to use more then one query or mutations in one react component for example. And if I want to mutate this contract I have to write a mutation. And if I do it with rest api I just have to open a put request endpoint and that is.
I am sorry you feel that way (about the writeup not about GraphQL 😁).
GraphQL solves some specific issues but is obviously not a tool to be applied everywhere.
Writing schemas and doing elaborate setup can be minimized by using tools like TypeORM, Prisma, or using a tech-stack like Hasura or PostGraphile.
Great article! Well explained for a beginner like me. Thanks a lot :)