Contentful is a big player in the headless CMS market and will probably continue to be one for a while. Nonetheless, there are some pain points when working with Contentful, such as SDK issues and REST, and a growing number of developers are looking for alternatives. In this article, I want to compare working with Contentful's REST API and GraphCMS' GraphQL API and show advantages and disadvantages of the different approaches.
The main difference between GraphCMS and Contentful is the underlying API technology. With GraphCMS we have GraphQL - a query language for APIs open-sourced by Facebook. With Contentful we have REST - a programming paradigm for distributed systems. While REST is the go-to standard, GraphQL is gaining a lot of traction and more and more developers want to get their hands on it. Both technologies allow talking to an API to retrieve and send data, which then can be consumed by any frontend. There are, however, critical differences. Let’s go through them!
Before we start, for the following examples we will be using a data model I prepared. It looks as follows:
You can play around yourself here
REST - ContentfulAnchor
Querying a REST API can be difficult at times, but if you are used to it, you'll probably know the gist. Let's take Contentful's Content Delivery API - one of the four main APIs. The others being Content Management, Content Preview, and Images API. Each API fulfills a different purpose – showing published entries, creating and deleting content, previewing drafts, and delivering images.
A typical GET request to the Content Delivery API would look something like this:
The ID after spaces is the ID of my test space, and entries meaning to send a response with all entries in that space.
The response looks something like this and gives you an overview of all your entries with their IDs, names and meta data.
GraphQL - GraphCMSAnchor
A huge benefit with GraphQL is the single endpoint for performing both read and write operations. A GraphQL query to fetch all data in the CMS might look like this:
We have a Content Model that includes League, Division, Team, Player, and Stadium. You can query all of these with this example. At first it seems like a lot more lines of code than a GET request with REST. What you are really doing, however, is defining a structure in which the API will return your data. This way you will know exactly what response the API will provide and there will be no unnecessary data you didn’t ask for.
What really makes the difference here is also the API Explorer of GraphCMS. Once you start writing a query you will get hints about which data is available. You can also access the auto-complete hints by pressing CTRL+Space:
The response will look exactly like the structure that you defined in the query:
If now you want to have less data in the query, for example excluding a player’s last name, you can simply leave it out of the query and it won't get returned. Alternatively, for more data, you simply add the necessary fields into your query. The data will now be returned in the response. This allows for true multi-platform queries, where data for the web client can look different than for a mobile client without extra work on the client-side.
To add content through the Contentful API we would use the Content Management endpoint. The endpoint is now
api.contentful.com/spaces/<SPACE_ID>/entries instead of
cdn.contentful.com. To perform a write action a POST request is required. We also need to define a body with the data to be added:
The response, if successful, will return the newly created entry with all the system fields and metadata. A major downside with REST is the missing possibility of adding nested or linked entries in one query. For every linked entry a new query is required and another one to create the link between them.
With GraphQL, adding entries is as simple as querying them. We simply need the keyword
mutation instead of
query. The endpoint is exactly the same as before. Here’s an example mutation for adding a new team:
In line 2 to 4, we define the mutation and what data we want to create. The following lines define the response format of the mutation:
As you can see, creating entries with GraphQL is straightforward and can be done very quickly. It gets even more interesting with nested queries: where you would need multiple POST requests with REST, you write a single GraphQL-Mutation. Don't worry if the query looks complicated at first sight, we will dig deeper into it:
We are sending a
createTeam mutation with a few parameters. The first one (line 3) is
divisionId, which links the team we are creating to its respective division. Next, we set the
teamName, which is a field from
Team. After that we directly create a new stadium and also link it to the team. Lastly, we also create a new player and automatically create a link to the team. Instead of many REST requests, we did all of that with a single call to the API! All that is possible because all the Models are already connected through relations.
If you wanted to do the same with a REST API, you would need to send a request for every entry you wanted to create and also another request each to create appropriate links. It's definitely a lot more work and the code gets more confusing.
Contentful also offers nested queries or
Links how they call them. You can link two entries from different content models with the
Link. To link a player to a team you would send a POST request with a body like this:
An essential tool when querying APIs is filtering. You don't always need every entry you have created, sometimes a selected piece is enough, e.g., the latest blog post or a specific team someone searched for.
Contentful specifically offers a wide range of filters, from filtering for content types, ordering, limits to full-text searches.
As a specific example we now want to filter
Players for their
birthDate greater than
The URL might look something like this:
The URL is pretty straight-forward. Not the prettiest but does the job.
Now comes the really fun part of GraphQL. Combining the querying flexibility of GraphQL with filtering, you have complete control over what data and exactly in which format you receive., A quick word of warning: the filter logic doesn’t come built-in with GraphQL,it has to be implemented server-side. So the filtering in GraphCMS can be different to other GraphQL services/servers.
A query for the same filter would look like this:
Also a pretty straight forward query, and with the autocompletion in the API Explorer it's really easy to see which filters are available.
The response, of course, looks exactly like we requested it:
Both CMS offer a good range of API tools and possibilities. Contentful does its job at maintaining a good REST API, but at the end of the day it's still REST. Doing simple requests can become very complex and tedious if you have a lot of data, especially if the data is relational. That's where GraphQL really shines: the developer experience is far more advanced and it's really easy and fun to dive deeper into the GraphQL matrix. Even more advanced queries, such as creating data with deeply nested elements, are pretty easy to understand and implement in your own system.
In the end, it is really up to you - do you prefer REST and like the ways you handle requests with it and access data across multiple endpoints? Go for Contentful and live a (maybe) happy life! If, on the other hand, you would like to experience simple querying, easy setup and, most importantly, an advanced developer experience? You should definitely take a look at GraphQL. If you also need a headless CMS, we at GraphCMS would be happy to help!
First True Multi-Platform Headless CMSAnchor
While Contentful offers a wide range of SDK, it is still not easy to implement it in just about any digital platform of your choosing. An SDK might be missing or out of date.
Here's where GraphCMS and GraphQL come into play: GraphQL is the first technology to allow true multi-platform use-cases. If your frontend can fetch JSON data you are good to go! Connected fridges, smartwatches, even cars and virtual reality headsets can access data with minimal effort and have it in exactly the format each of them needs. If this doesn't convince you, I don't know what else can!
Feel free to also give our product a go for yourself. We offer free trials and for hobby or test projects you can use our forever free Free plan. Learn more here.