For most digital products, communication between the Client and Server is one of the most vital parts. Over the years, there have been many attempts to make this more efficient and streamlined.
One of the first approaches for handling client-server communication is Remote Procedure Calls (RPC). Here, the client calls a function/procedure on the server through the request.
As an example, consider a to-do list application. A user using this application can create/view “lists.” A list can contain a set of “Items.” Users can add/delete “items” in the “list,” and move an “item” from one “list” to another.
There are a few challenges with this approach,
● Exposing the functions and implementation details to the client introduces tight coupling between client and server code. Every time a change is to be made on the server, the corresponding client code should be updated as well.
● Another issue is discoverability. There's no direct way for the client to know that a given Application Programming Interface (API) exists. Usually, supporting external documentation outlining such details will have to be shared.
● For each specific requirement, one could end up adding a new function on server-side code, which will return the exact data required by the client. But such a practice will soon result in something called “function explosion”. Where there are numerous unnecessary functions in the server side code, each of which is useful to one specific request.
In 2000, REpresentational State Transfer (REST) was introduced.
The main idea in REST is that any information that needs to be exposed to the client will be abstracted as a resource. The client can view/update the state of these resources through requests to the server.
To refer to an interface as RESTful six constraints must be satisfied.
1. Client-server
2. Uniform interface
3. Stateless
4. Cacheable
5. Layered System
6. Code on demand
Let us design the same to-do application now with REST. First, we have to identify the objects in our domain and represent them as resources. Here list and item are good choices for resources to be exposed through API. The set of API calls mentioned above will transform as follows.
● GET /lists
● GET /lists/42/items
● POST /lists/42/items
● DELETE /items/24
GET /lists fetches all the lists. GET/lists/42/items fetches all the items in a list with id 42 and so on. There's no tight coupling, and the client will be able to navigate through the APIs using hyperlinks provided.
● Large payloads: A RESTful API will always respond with a resource. All the fields in a resource may or may not be relevant to the client all the time. Thus, the client will end up processing a large payload.
● Increased round trips between client and server: A client could end up making multiple requests to the server to fetch relevant data. This will increase the number of requests to the server and could affect the performance of both the server and client.
On a powerful device connected to a high-speed network, both of these problems are hardly noticeable.
But, when a user on a mobile device tries to get something from the application, the above problems will throttle performance and make the application unusable.
This was the exact problem engineers at Facebook faced in 2012, and the project they undertook to solve the problem evolved into “GraphQL”.
To quote the official documentation
GraphQLis a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API; gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.
GraphQL is an alternative approach to client-server communication. It is a specification, which outlines the structure and behavior of request and response that are to be exchanged between a client and a server.
GraphQL doesn't mandate a particular programming language or storage system for application servers that implement it. There are numerous implementations of GraphQL in various languages/frameworks.
It facilitates efficient and effective communication between client and server.
In the initial stages, GraphQL’s main goal was to tackle the problems of large payloads and multiple round trips. It solves this problem by giving clients the power to ask for exactly what they need and nothing more.
Let us consider the to-do app example, again. We have the same requirement: client wants to know the “name” field of the first item in the second list in application. With GraphQL, the contents of the request and response exchanged through API calls could look as follows:
The client sent only one request to the server, and received one response, which contained the exact required field. Value for the field is “Write” as we can see in the above example.
Since the client can ask what it wants and get exactly what it needs in a single round-trip both the problems of processing large payloads and multiple round trips are avoided here.
We used a query type request; these are used for reading the data. The query accepts an optional argument; if optional arguments are present, the server could use them to narrow the search and filter the data. Here, we're interested in the second list only. Thus we pass positions:[1] when communicating our requirements to the server.
Inside the list, we only mentioned items; this will inform the server that we are only interested in that field and other fields aren't required. Items field accepts an optional parameter position, which is an array. We're interested only in the first item; thus we pass positions[0].Inside items, we mention name; this cues the server that it should include only the name field in the response.
Here is a comparison graphic to summarize our discussion:
GraphQL is a robust approach and a very good choice for certain scenarios. Unfortunately, there's no one-size-fits all answer, but we've seen GraphQL work in most scenarios.
To determine the best approach for your product development, you must ascertain which guarantees are essential and intolerable constraints on your API design.
GraphQL is an especially good choice when designing a mobile-first user experience. It helps erode response delays with limited computing power and slower networks, making for a better user experience.
GraphQL simplifies querying with complex schemas, and improves developer productivity.
Like any other solution, GraphQL has a few constraints.
Using GraphQL you can request and receive only the relevant data; this is achieved by moving the responsibility of “getting the relevant data” from the client onto the server.
Instead of the client parsing a large payload, the server now parses a relatively complex request. Depending on the request, the server will hit the database (multiple times if needed) and aggregate all the relevant data that was requested. The server then prepares the response as per the request and sends it back to the client.
Although the client here's doing less work, the back-end is doing more work. If you engineered your system correctly, the amount of processing work done by the back-end only increases moderately. If you didn’t follow best practices, the number of calls between server and database could increase and slow down performance.
It’s tricky, often requiring customized engineering effort, to handle coaching, authorization, versioning, and pagination effectively.
Getting GraphQL right is hard.
A successful example of a large-scale application using GraphQL in production is GitHub’s switch from API to GraphQL. They maintain a GraphQL explorer for their API, through which one could explore production data in real-time.
An earlier version of this blog was published on Medium by the author.
For most digital products, communication between the Client and Server is one of the most vital parts. Over the years, there have been many attempts to make this more efficient and streamlined.
One of the first approaches for handling client-server communication is Remote Procedure Calls (RPC). Here, the client calls a function/procedure on the server through the request.
As an example, consider a to-do list application. A user using this application can create/view “lists.” A list can contain a set of “Items.” Users can add/delete “items” in the “list,” and move an “item” from one “list” to another.
There are a few challenges with this approach,
● Exposing the functions and implementation details to the client introduces tight coupling between client and server code. Every time a change is to be made on the server, the corresponding client code should be updated as well.
● Another issue is discoverability. There's no direct way for the client to know that a given Application Programming Interface (API) exists. Usually, supporting external documentation outlining such details will have to be shared.
● For each specific requirement, one could end up adding a new function on server-side code, which will return the exact data required by the client. But such a practice will soon result in something called “function explosion”. Where there are numerous unnecessary functions in the server side code, each of which is useful to one specific request.
In 2000, REpresentational State Transfer (REST) was introduced.
The main idea in REST is that any information that needs to be exposed to the client will be abstracted as a resource. The client can view/update the state of these resources through requests to the server.
To refer to an interface as RESTful six constraints must be satisfied.
1. Client-server
2. Uniform interface
3. Stateless
4. Cacheable
5. Layered System
6. Code on demand
Let us design the same to-do application now with REST. First, we have to identify the objects in our domain and represent them as resources. Here list and item are good choices for resources to be exposed through API. The set of API calls mentioned above will transform as follows.
● GET /lists
● GET /lists/42/items
● POST /lists/42/items
● DELETE /items/24
GET /lists fetches all the lists. GET/lists/42/items fetches all the items in a list with id 42 and so on. There's no tight coupling, and the client will be able to navigate through the APIs using hyperlinks provided.
● Large payloads: A RESTful API will always respond with a resource. All the fields in a resource may or may not be relevant to the client all the time. Thus, the client will end up processing a large payload.
● Increased round trips between client and server: A client could end up making multiple requests to the server to fetch relevant data. This will increase the number of requests to the server and could affect the performance of both the server and client.
On a powerful device connected to a high-speed network, both of these problems are hardly noticeable.
But, when a user on a mobile device tries to get something from the application, the above problems will throttle performance and make the application unusable.
This was the exact problem engineers at Facebook faced in 2012, and the project they undertook to solve the problem evolved into “GraphQL”.
To quote the official documentation
GraphQLis a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API; gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.
GraphQL is an alternative approach to client-server communication. It is a specification, which outlines the structure and behavior of request and response that are to be exchanged between a client and a server.
GraphQL doesn't mandate a particular programming language or storage system for application servers that implement it. There are numerous implementations of GraphQL in various languages/frameworks.
It facilitates efficient and effective communication between client and server.
In the initial stages, GraphQL’s main goal was to tackle the problems of large payloads and multiple round trips. It solves this problem by giving clients the power to ask for exactly what they need and nothing more.
Let us consider the to-do app example, again. We have the same requirement: client wants to know the “name” field of the first item in the second list in application. With GraphQL, the contents of the request and response exchanged through API calls could look as follows:
The client sent only one request to the server, and received one response, which contained the exact required field. Value for the field is “Write” as we can see in the above example.
Since the client can ask what it wants and get exactly what it needs in a single round-trip both the problems of processing large payloads and multiple round trips are avoided here.
We used a query type request; these are used for reading the data. The query accepts an optional argument; if optional arguments are present, the server could use them to narrow the search and filter the data. Here, we're interested in the second list only. Thus we pass positions:[1] when communicating our requirements to the server.
Inside the list, we only mentioned items; this will inform the server that we are only interested in that field and other fields aren't required. Items field accepts an optional parameter position, which is an array. We're interested only in the first item; thus we pass positions[0].Inside items, we mention name; this cues the server that it should include only the name field in the response.
Here is a comparison graphic to summarize our discussion:
GraphQL is a robust approach and a very good choice for certain scenarios. Unfortunately, there's no one-size-fits all answer, but we've seen GraphQL work in most scenarios.
To determine the best approach for your product development, you must ascertain which guarantees are essential and intolerable constraints on your API design.
GraphQL is an especially good choice when designing a mobile-first user experience. It helps erode response delays with limited computing power and slower networks, making for a better user experience.
GraphQL simplifies querying with complex schemas, and improves developer productivity.
Like any other solution, GraphQL has a few constraints.
Using GraphQL you can request and receive only the relevant data; this is achieved by moving the responsibility of “getting the relevant data” from the client onto the server.
Instead of the client parsing a large payload, the server now parses a relatively complex request. Depending on the request, the server will hit the database (multiple times if needed) and aggregate all the relevant data that was requested. The server then prepares the response as per the request and sends it back to the client.
Although the client here's doing less work, the back-end is doing more work. If you engineered your system correctly, the amount of processing work done by the back-end only increases moderately. If you didn’t follow best practices, the number of calls between server and database could increase and slow down performance.
It’s tricky, often requiring customized engineering effort, to handle coaching, authorization, versioning, and pagination effectively.
Getting GraphQL right is hard.
A successful example of a large-scale application using GraphQL in production is GitHub’s switch from API to GraphQL. They maintain a GraphQL explorer for their API, through which one could explore production data in real-time.
An earlier version of this blog was published on Medium by the author.
For most digital products, communication between the Client and Server is one of the most vital parts. Over the years, there have been many attempts to make this more efficient and streamlined.
One of the first approaches for handling client-server communication is Remote Procedure Calls (RPC). Here, the client calls a function/procedure on the server through the request.
As an example, consider a to-do list application. A user using this application can create/view “lists.” A list can contain a set of “Items.” Users can add/delete “items” in the “list,” and move an “item” from one “list” to another.
There are a few challenges with this approach,
● Exposing the functions and implementation details to the client introduces tight coupling between client and server code. Every time a change is to be made on the server, the corresponding client code should be updated as well.
● Another issue is discoverability. There's no direct way for the client to know that a given Application Programming Interface (API) exists. Usually, supporting external documentation outlining such details will have to be shared.
● For each specific requirement, one could end up adding a new function on server-side code, which will return the exact data required by the client. But such a practice will soon result in something called “function explosion”. Where there are numerous unnecessary functions in the server side code, each of which is useful to one specific request.
In 2000, REpresentational State Transfer (REST) was introduced.
The main idea in REST is that any information that needs to be exposed to the client will be abstracted as a resource. The client can view/update the state of these resources through requests to the server.
To refer to an interface as RESTful six constraints must be satisfied.
1. Client-server
2. Uniform interface
3. Stateless
4. Cacheable
5. Layered System
6. Code on demand
Let us design the same to-do application now with REST. First, we have to identify the objects in our domain and represent them as resources. Here list and item are good choices for resources to be exposed through API. The set of API calls mentioned above will transform as follows.
● GET /lists
● GET /lists/42/items
● POST /lists/42/items
● DELETE /items/24
GET /lists fetches all the lists. GET/lists/42/items fetches all the items in a list with id 42 and so on. There's no tight coupling, and the client will be able to navigate through the APIs using hyperlinks provided.
● Large payloads: A RESTful API will always respond with a resource. All the fields in a resource may or may not be relevant to the client all the time. Thus, the client will end up processing a large payload.
● Increased round trips between client and server: A client could end up making multiple requests to the server to fetch relevant data. This will increase the number of requests to the server and could affect the performance of both the server and client.
On a powerful device connected to a high-speed network, both of these problems are hardly noticeable.
But, when a user on a mobile device tries to get something from the application, the above problems will throttle performance and make the application unusable.
This was the exact problem engineers at Facebook faced in 2012, and the project they undertook to solve the problem evolved into “GraphQL”.
To quote the official documentation
GraphQLis a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API; gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.
GraphQL is an alternative approach to client-server communication. It is a specification, which outlines the structure and behavior of request and response that are to be exchanged between a client and a server.
GraphQL doesn't mandate a particular programming language or storage system for application servers that implement it. There are numerous implementations of GraphQL in various languages/frameworks.
It facilitates efficient and effective communication between client and server.
In the initial stages, GraphQL’s main goal was to tackle the problems of large payloads and multiple round trips. It solves this problem by giving clients the power to ask for exactly what they need and nothing more.
Let us consider the to-do app example, again. We have the same requirement: client wants to know the “name” field of the first item in the second list in application. With GraphQL, the contents of the request and response exchanged through API calls could look as follows:
The client sent only one request to the server, and received one response, which contained the exact required field. Value for the field is “Write” as we can see in the above example.
Since the client can ask what it wants and get exactly what it needs in a single round-trip both the problems of processing large payloads and multiple round trips are avoided here.
We used a query type request; these are used for reading the data. The query accepts an optional argument; if optional arguments are present, the server could use them to narrow the search and filter the data. Here, we're interested in the second list only. Thus we pass positions:[1] when communicating our requirements to the server.
Inside the list, we only mentioned items; this will inform the server that we are only interested in that field and other fields aren't required. Items field accepts an optional parameter position, which is an array. We're interested only in the first item; thus we pass positions[0].Inside items, we mention name; this cues the server that it should include only the name field in the response.
Here is a comparison graphic to summarize our discussion:
GraphQL is a robust approach and a very good choice for certain scenarios. Unfortunately, there's no one-size-fits all answer, but we've seen GraphQL work in most scenarios.
To determine the best approach for your product development, you must ascertain which guarantees are essential and intolerable constraints on your API design.
GraphQL is an especially good choice when designing a mobile-first user experience. It helps erode response delays with limited computing power and slower networks, making for a better user experience.
GraphQL simplifies querying with complex schemas, and improves developer productivity.
Like any other solution, GraphQL has a few constraints.
Using GraphQL you can request and receive only the relevant data; this is achieved by moving the responsibility of “getting the relevant data” from the client onto the server.
Instead of the client parsing a large payload, the server now parses a relatively complex request. Depending on the request, the server will hit the database (multiple times if needed) and aggregate all the relevant data that was requested. The server then prepares the response as per the request and sends it back to the client.
Although the client here's doing less work, the back-end is doing more work. If you engineered your system correctly, the amount of processing work done by the back-end only increases moderately. If you didn’t follow best practices, the number of calls between server and database could increase and slow down performance.
It’s tricky, often requiring customized engineering effort, to handle coaching, authorization, versioning, and pagination effectively.
Getting GraphQL right is hard.
A successful example of a large-scale application using GraphQL in production is GitHub’s switch from API to GraphQL. They maintain a GraphQL explorer for their API, through which one could explore production data in real-time.
An earlier version of this blog was published on Medium by the author.