As clearly described on "How to GraphQL", GraphQL was developed to cope with the need for more flexibility and efficiency, that is, to solve many of the shortcomings and inefficiencies that developers experience when interacting with REST APIs.
With a REST API, you would typically gather the data by accessing multiple endpoints, and each of these endpoints would normally expect a predefined set of parameters and would return data according to a predefined logic and structured in a predefined way.
With a GraphQL API, instead, you would have a much smaller number of endpoints (e.g. one for each application area), accepting a query as a parameter and returning data whose semantics and structure depends entirely on the specific query.
When a backend exposes a GraphQL API, for instance, frontend developers can create new client application or extend existing ones without bothering any backend developer. In fact, they just need to invoke the same GraphQL endpoints with different queries, thus retrieving exactly the data they need, structured exactly as they need it.
NOTE: flexibility inevitably comes with potential risks. In fact, without a well a well-defined security policy, the greater expressive power of GraphQL might be exploited by malicious clients to retrieve from the backend data they should not be able to retrieve. For this reasons, Livebase Models incorporate layers defining users profiles and their permissions, which are always respected in the generated GraphQL APIs.
By retrieving exactly the data they need, structured exactly as they need it, GraphQL solve the common over-fetching and the under-fetching problems of REST APIs.
Such problems happen because, since REST endpoints return rigidly predefined data structures, so it’s very difficult to design the API in a way that it’s able to provide clients with their exact data needs.
Under-fetching with REST APIs often come with another problems knowns as the "n+1 requests problem": when a specific endpoint doesn’t provide enough of the required information, the client will have to make additional requests to fetch everything it needs. This can escalate to a situation where a client needs to first download a list of elements, but then needs to make one additional request per element to fetch the required data.
As perfectly described in the above-mentioned "How to GraphQL", a common pattern with REST APIs is to structure the endpoints according to the views that you have inside your app. This is handy since it allows for the client to get all required information for a particular view by simply accessing the corresponding endpoint.
The major drawback of this approach is that it doesn’t allow for rapid iterations on the frontend. With every change that is made to the UI, there is a high risk that now there is more (or less) data required than before. Consequently, the backend needs to be adjusted as well to account for the new data needs. This kills productivity and notably slows down the ability to incorporate user feedback into a product.
With GraphQL, this problem is solved. Thanks to the flexible nature of GraphQL, changes on the client-side can be made without any extra work on the server. Since clients can specify their exact data requirements, no backend engineer needs to make adjustments when the design and data needs on the frontend change.
In REST APIs, there isn't a concept of a schema or type system. On the other hand, GraphQL has a strong type system to define what the API looks like, and a schema is defined with fields mapped to types and serves as a contract between the client and the server. This schema contract lets the frontend and backend developers to work independently with a guarantee that the data requirements are met.
Schema and type system allow a number of independent tools to support developers in detecting client/server integration problems at compile-time, rather than at run-time.
Furthermore, having a schema allows GraphQL API to be self-documenting and optionally discoverable via reflection (that is, the API can natively provide clients with information on itself and on its usage).