Learn how the open standard for querying data is different from REST and Swagger, and how you can use it to build more flexible and responsive APIs. Credit: Lightspring / Shutterstock When most software developers think of web APIs, we think of REST, or Representational State Transfer. With REST, you send a request to a request-specific URL and receive the results in whatever format makes sense for the application. Meta’s web API system, GraphQL, is a different kind of API. With GraphQL, developers use a strongly typed query language to define both requests and responses, allowing an application to specify exactly what data it needs from an API. Thus GraphQL is meant as a more efficient, structured, and systematic alternative to REST. In this article, you will learn how GraphQL differs from REST, how those differences impact API design, and why GraphQL often makes a better choice than REST for fetching data from a server. GraphQL vs. REST With REST, you typically submit your request by way of a specially crafted URL, with each variety of request sent to a different endpoint—for instance, /movie/2120 vs. /director/5130. With GraphQL, you submit a declarative request in a JSON-like query for the data you’re seeking, and all requests go to the same endpoint. The schema used for the request determines what data you’ll get back. It’s a standardized, self-describing way to ask for the specific data you need, and only the data you need. Using different schemas for different types of requests, rather than a different endpoint URL format, makes for a much more flexible query mechanism. Although many REST APIs also conform to a common specification, Swagger, there’s no rule that says a REST API has to be generated by Swagger. GraphQL provides a formal definition for the API by default. In this respect, GraphQL is a little like SQL. With an SQL-powered data source, you connect to one common endpoint for all your data requests, and the formatting of the request determines what records you’ll get back. And while there are many different implementations of SQL, the syntax of SQL queries remain highly consistent across those implementations. GraphQL queries So, we’ve already said that GraphQL uses a schema, or a data definition, to describe how the data to be retrieved is organized in the query and the response. Anyone who has worked with an ORM (object-relational mapper) should find GraphQL’s data schema definitions familiar. Here’s an example: type Movie { id: ID title: String released: Date director: Director } type Director { id: ID name: String movies: [Movie] } You’ll notice that each element in the schema has a type definition. GraphQL has its own type system for queries, which is used to validate the incoming schema and to return data in a format consistent with the definition. Queries submitted to GraphQL are similarly defined by a schema: type Query { movie_title(title: String!): Movie director(id: ID): Director } Here we have a query that takes in up to two parameters, movie_title (by way of its title), and director (also by way of an ID.) The ! next to a type indicates that this is a mandatory element in the query. In other words, you must query for a movie by title, with the director being optional (as a way to narrow the query). Mandatory elements can also be used in a data schema. Here’s one possible way to format a query that searches for movies by their ID only: query GetMovieByID ($id: ID!) { movie(id: $id) { name } } This query uses a separately defined variable ($id), which is required, to look up a movie by its ID number and return its name. Note that GraphQL queries can return related objects and their fields, not just individual fields. It does this by nesting arrays of items inside fields. Variables for queries are passed along in a separate section of the query, using a format like this: { “id”: 23 } GraphQL types GraphQL’s query type system specifies many common scalar types, like strings and integers. Most queries will revolve around those. But the type system also includes several advanced types for more sophisticated queries: The interface type can be used to create an abstract type with a pre-defined set of fields, which other types can implement and re-use. The union type allows different kinds of results to be returned across multiple types from a single kind of query. input types can be used to pass whole objects of the above kind as parameters in a query, provided those objects are created out of common scalar types that can be validated. If you’re working with interface or union objects, you’ll need to use inline fragments and directives to return data based on the conditions those object types can specify. Another kind of type that can be returned in a query is the edge type, returned in an optional edges field. Edges contain nodes—data records—and cursors, which are encoded strings that provide contextual information about how to paginate backwards or forwards from that object. { movie { name actors (first:5) { edges { cursor node { name } } } } } In this example, a movie node would return the name of the movie and its actors. For each actor in the movie, we’d receive a node containing the actor’s name and a cursor that allows browsing the actor’s “neighbors.” Pagination with GraphQL A common scenario when working with any data source is to request data in pages by way of a cursor. GraphQL provides a number of ways to do pagination. When you request records, you can specify not only how many records to request and the starting offset, but how to request successive pages. The example code in the previous section returns only the first five actors associated with a given movie—as indicated by the first:5 parameter in parentheses. The first: clause after actors can be followed by other keywords that describe how to fetch the succeeding items. offset: can be used for simple offsets, but the offset might be thrown off when data is added or deleted. For the most robust pagination, you’ll want to use a cursor that can be delivered along with the object you’re requesting, by using the edge type described above. This allows you to create pagination mechanisms that are not disrupted when data is inserted or deleted between paginations—for instance, by using the object’s unique ID (or any other attribute as long as it’s unique) as a starting key index for other calculations. Changing data with GraphQL mutations With a REST API, you make changes to the server-side data by submitting requests that use POST, PATCH, and other HTTP verbs. With GraphQL, you use a specific query schema to make changes, a mutation query—again, in much the same way SQL uses UPDATE or DELETE queries. To make changes to the data, you submit a GraphQL query using a schema called a mutation schema: mutation CreateMovie ($title: String!, $released: Date!) { createMovie (title: $title, released: $released){ id title released } } [submitted data] { “title”: “Seven Samurai” “released”: “1950” } All queries, including mutation queries, can return data. Here, the list of fields in the curly braces after createMovie specifies what we want to see returned from the server after a new record is created with this request. The value for the id field, in this case, would be created by the database; the values for the other fields are submitted in the query. Another thing to keep in mind is that the queries and data types used to return data are by design different from those used to request data. Mutation queries need to validate incoming data, so the types used for those queries are meant to serve that function. Likewise, the fields used in returned query objects are for display, not validation. If you take in a GraphQL object as returned from a query, it might have fields with circular references or other issues that make it unusable as a query parameter. Why use GraphQL? A key reason to choose GraphQL over REST is the explicit, declarative nature of GraphQL queries. Having a formal definition for how queries and returned data should look has advantages aside from being consistent across APIs and implementations. As API evangelist Phil Sturgeon noted in his examination of GraphQL vs. REST, the field structure of GraphQL makes it easier to apply more granular versioning to queries, since specific fields can be deprecated or rolled in over time as opposed to versioning the entire API. It’s still possible to take the wholesale versioning approach with GraphQL; the point is that you aren’t forced to do so when rolling out changes. Sashko Stubailo, engineering manager at Apollo GraphQL, maker of open source tools for GraphQL APIs, notes another advantage of the GraphQL approach: It’s self-documenting. “Every possible query, object, and field comes with a name, description, and type information that can be queried from the server in a standard way,” Stubailo writes. The self-documenting nature of GraphQL also provides a sort of introspection, meaning you can use queries to return information about themselves. This way, software that works with GraphQL queries doesn’t have to be hard-wired to work with any particular field set; it can infer the fields automatically. The fact that GraphQL is newer and REST/Swagger are older should not, by itself, be a reason to favor GraphQL. As Arnaud Lauret, author of The Design of Everyday APIs said in a discussion of the two standards: “A GraphQL API, just like a REST one, must be created with a purpose and designed from an outside-in perpective and not an inside-out one.” Related content opinion The dirty little secret of open source contributions It isn’t the person making the contributions—it’s how easy the contributions make it to use the software. By Matt Asay Nov 18, 2024 4 mins Technology Industry Open Source news ‘Package confusion’ attack against NPM used to trick developers into downloading malware Attackers gunning for supply chains again, deploying innovative blockchain technique to hide command & control. By John E. Dunn Nov 06, 2024 4 mins Vulnerabilities Open Source Security news Meta offers Llama AI to US government for national security US government agencies and private sector partners can now use the Llama model, but many other restrictions on its use remain. By Prasanth Aby Thomas Nov 05, 2024 1 min Generative AI Open Source Artificial Intelligence news OSI unveils Open Source AI Definition 1.0 The Open Source AI Definition will provide a reference for determining whether an AI system is truly open source AI, OSI said. By Lynn Greiner Oct 28, 2024 7 mins Generative AI Open Source Artificial Intelligence Resources Videos