6 reasons to stop using REST and start using GraphQL

Following up the post about a Rails API only app, lets talk about why you should not use REST in your API app.

1: too much unneeded information

Have you ever written a client application to any API? And when you did it, was there a query you needed to do that returned a lot more information than you needed?

It happens to me a lot, last week I was writing a report using PostmarkApp API and I needed to list all the events from a lot of different messages I’ve sent, and to do that, I had to download a lot of information I didn’t need about the messages, including the body of the message in plain text and HTML.

And this does not happen only to PostmarkApp, almost every API out there has the same problem deppending on what the user wants to do

2: you are not a clairvoyant

It is almost impossible to know before hand all the great things the clients to your API will create in the future, and with REST you would need to create lots of bloated methods, or a lot of very specific methods that could be never used.

3: if you have mobile clients to your API they probably care about their bandwidth usage

I know most of the time, for a desktop computer we never think about bandwidth anymore, we send links to users to download huge files, create APIs that return a lot of information the user does not need, and we do not even care about the bandwidth usage of our servers because nowadays it is really cheap.

But when you have a mobile client, the reality is not exactly the same, and if that client is not in a first world country, they might not have a very good connection at all (yes, that is my reality 😀 )

So a mobile client, usually needs an API that returns only the needed information for that screen or for that logic, to avoid delays and other problems, like spending all your user internet data plan…

4: you will evolve and v1, v2, vx in the URL is a shitty solution

When doing REST any change in the API is usually considered a new version, to add new fields, …

In GraphQL you can just evolve the schema, and new API clients can use the new provided fields.

So there is less reasons to create shitty URLs.

5: security matters

I’m not saying here that security is not possible with REST, but since in GraphQL you can specify what fields you want in the result, it is also possible to allow some users to see one field and not see another from the same model, in the same API call.

Facebook does that a lot in their GraphQL API, with basic security you can access users email and name, to get more information you need to ask for permission, or have you application registered and in production…

What I’m saying is that GraphQL allows for a more fine grained security implementation.

6: it is easy to implement

Lets stop with the easy talk do do a simple exercise?

create a new rails app with the command:
rails new graphqasample --api --skip-test

Now we’ll add the following line to our Gemfile

gem "graphql"

And run the commands:

bundle install
rails g graphql:install

Now we are ready to start playing with GraphQL in our API app.

To start, we’ll need some rails Models, different from most rails apps, only the database schema is not enough, we’ll need to tell GraphQL what fields are available/permitted for each object.

So, lets start creating a simple “schema” for our database, with these commands:

And now, lets expose this “blog” using GraphQL, starting with the user model, to do that, create the file app/graphql/user_type.rb with this content:

# defines a new GraphQL typeTypes::UserType = GraphQL::ObjectType.definedo# this type is named `User`
name 'User'# it has the following fields
field :id, !types.ID
field :username, !types.String
field :first_name, !types.String
field :last_name, !types.String
field :birth_date, !types.Date
field :posts, ->{ !types[Types::PostType]}end

In a graphql model we define the valid fields and the references, this user type references the PostType, so we need to define it in the file app/graphql/post_type.rb

# defines a new GraphQL typeTypes::PostType = GraphQL::ObjectType.definedo# this type is named `Post`
name 'Post'# it has the following fields
field :id, !types.ID
field :title, !types.String
field :body, !types.String
field :comments, ->{ !types[Types::CommentType]}end

And this post type refecenres the comment type, and we need to define it in the app/graphql/comment_type.rb

# defines a new GraphQL typeTypes::CommentType = GraphQL::ObjectType.definedo# this type is named `Comment`
name 'Comment'# it has the following fields
field :id, !types.ID
field :body, !types.String
field :owner, !types.Stringend

Now that we have all the types defined, we can enable the query to any one of them or to only one of them, but we need at least one (the User or Post are good options), and to do that, we need to edit the file app/graphql/query_type.rb