Livebase adopts and promotes GraphQL as the primary means of accessing generated applications because it offers significantly more flexibility to our integrators than the traditional REST API. GraphQL’s graph approach and type system are in line with many principles of Livebase modeling.
Livebase generates a distinct GraphQL API for each application view (Application Schema) defined in the engine of an enabled Cloudlet. The Cloudlet exposes an endpoint that offers an API based on the GraphQL Schema generated from the classes, attributes, and relationships managed on that application view; you can query the endpoint to read and/or modify the object graphs or even invoke plugins.
In this guide:
- in GraphQL diagram we describe the basic terminology and conventions used by Livebase to map classes, attributes, relationships, and error messages to GraphQL types and fields;
- in Forming GraphQL calls we see, through examples, how to communicate with Cloudlet’s GraphQL API;
- in GraphiQL we see another way to interact with GraphQL through Cloudlet’s available integrated development environment.
- The GraphQL Livebase API supports the following use cases:
- Read data
- Write data (creating, editing, deleting and validating)
- Invoking plugins
- Get or release locks on objects
- Retrieve historical records
Quick links #
Here are some useful links to get you started with Livebase’s GraphQL API:
What is GraphQL #
GraphQL is an API access mechanism that provides a more efficient, powerful, and flexible alternative to traditional schemas, mainly the REST paradigm. Created to cope with the increase in internet traffic from mobile applications and the spread of increasingly complex and heterogeneous frameworks, GraphQL was developed by Facebook in 2012, initially as an internal project, and was then made open source as of 2015. Today, GraphQL is widely adopted and managed by the GraphQL Foundation, comprised of industry-leading companies such as Airbnb, Facebook, GitHub, and Twitter.
GraphQL proposes a declarative approach to data retrieval, where clients specify precisely what information they want to retrieve from the API, with an emphasis on predictability: the data and services that make up the GraphQL API are described in terms of data types, where each type consists of one or more fields containing its type specification. Clients are then provided with a GraphQL template that clearly documents all of the API’s services: what they do, what they receive as input, and what they return.
The GraphQL schema resides on the server and is used by the runtime system as an orientation point to validate requests and reject incorrect queries; even in case of errors, the server can respond with descriptive and predictable messages.
GraphQL Language #
A GraphQL service is created by defining types and fields and then providing functions to populate each field on the type. From a practical standpoint, services can be written in any language; for this reason, GraphQL adopts a lingua franca to describe the schema to clients, called Schema Definition Language (SDL). This abstract and implementation-independent language is used to get clients and servers to agree on the data exchanged through the API.
For example, the following diagram describes a GraphQL service that allows you to read the name and age of an employee from his or her ID and trace it back to the name of the team to which it belongs:
# uno schema GraphQL
type Employee {
_id: ID
full_name: String
age: Int
team: Team
}
type Team {
_id: ID
name: String
}
type Query {
Employee__get(_id: ID!): Employee
}
The query language basically consists of selecting fields on the types defined on the schema. The server’s response is a JSON (JavaScript Object Notation) object whose fields exactly match those requested in the query.
# a GraphQL query
{
Employee___get(_id: "12345") {
full_name
age
team {
name
}
}
}
// server response
{
"data": {
"employee___get": {
"full_name": "John Smith",
"age": 35,
"team": {
"name": "Cool Coders"
}
}
}
}
As we see in the example, in GraphQL , the response’s content matches with the fields selected by the query, meaning that it is easy for a client to predict the result of a service even before executing a query.
Differences with REST #
GraphQL does not represent a complete break with REST but rather continues along the same path inheriting its main foundational elements:
- GraphQL is also based on the HTTP protocol (GraphQL calls are HTTP requests of type
POST
), and thus results in low overhead in communication between client and server; - like REST, GraphQL is a subtle interface: the schema is referenced to data structures defined in the application (not the database), and the requested data is returned regardless of which database it is stored in. Aspects such as authentication, caching, and query optimization are not handled directly by GraphQL and are delegated to the underlying application layer.
Flexible Queries #
The main difference with traditional REST APIs is that instead of mapping resources to multiple endpoints (each of which returns a fixed data structure), a GraphQL server exposes a single endpoint and allows clients to access multiple resources through a single request. In fact, REST’s rigidity in binding resources to endpoints (and consequently URLs) has always caused two problems:
- over-fetching, i.e., the situation where an endpoint responds too generically by offering a large amount of data that the client is forced to process again and again, even if it is only interested in a subset of the information;
- under-fetching (also called n+1 requests problem), the opposite situation to the previous one in which a specific endpoint does not provide enough information to the client, so the client is forced to make additional requests on other endpoints to retrieve everything it needs, with negative consequences in terms of efficiency and bandwidth consumption at each additional request (both for itself and for the server).
In GraphQL there are no rigid queries: any query that respects the schema is a valid query. This allows clients to write highly specialized queries in the use case of interest and minimize both the number of requests sent to the server and the amount of data exchanged. Different clients can then interact with the same API in radically different ways, consuming only the data they need.
Information discovery #
Over time, efforts have been made to make traditional REST APIs more flexible by giving clients some freedom in establishing the format of the request and response (e.g., by specifying parameters in the request URL) or by exposing many specialized endpoints. However, as complexity increases, it becomes difficult to document the information offered uniformly so that a client can consume it. Documenting a REST API is a responsibility left to the designer and does not follow a standard process.
In GraphQL, on the other hand, the schema itself documents the API in a standard way. The existence of a single centralized “graph” (as opposed to multiple REST endpoints) allows queries to be written as if they were “paths” that start at one entry point and reach different “nodes” in the schema. Whereas on REST, the developer is forced to consult the documentation on a web page, in GraphQL, he can query the schema directly for information about types and fields using introspective queries, or use a development tool that offers autocomplete functions, such as GraphiQL.
“Think in graphs, not endpoints.” Lessons From 4 Years of GraphQL.
Evolution and versioning #
In REST, API evolution has always been a limitation: updates to the frontend often require changes to the backend to accommodate new data requirements, conversely, changes to API services can compromise the operation of pre-existing client calls. For these two reasons, REST often uses API versioning (grouping endpoints of a given version under a common root, e.g. /api/v3/
) to ensure backward compatibility and gradual upgrades, but at the same time introduces more complexity in documenting existing services.
In GraphQL, on the other hand, there is no concept of versioning: since queries return only explicitly requested data, it is possible to prepare new types and fields without introducing substantial changes or compromising the correctness of calls already in production. Thanks to the flexibility of the language, clients have many options for adapting their calls without requiring additional work on the server or schema.
Further reading #
Benefits #
To recap, the strengths of GraphQL are:
- strong typing: the schema defines the API’s type system and all relationships between objects (as well as the validity of client calls), while the specification determines the validity of the schema on the server;
- flexibility: clients can navigate the hierarchy defined in the schema with highly specialized queries that minimize the number of calls and accurately request only the data they need;
- predictability: the format of a GraphQL query mirrors the content of the JSON response returned by the server;
- rapidity of evolution: the schema can evolve quickly without introducing versioning, while clients can adapt their calls without requiring additional work on the server or schema;
- introspection: Clients can query the schema to get details about the schema;
- interoperability: GraphQL offers a wide choice of libraries to implement both server and client, as well as powerful development tools.