Sofa — The best way to REST (is GraphQL)

Ending the REST vs GraphQL debate once and for all

Jan 25, 2019 · 7 min read
Activate REST API in a snap


  • Get most of the benefits of GraphQL on the backend and frontend, while using and exposing REST
  • Support all your existing clients with REST while improving your backend stack with GraphQL
  • Create custom, perfectly client-aligned REST endpoints for your frontend simply by naming a route and attaching a query
  • Stop arguing about REST vs GraphQL. Use GraphQL, generate REST and get the best from both
  • In the other way around (REST to GraphQL) you won’t get the best of both world but less powerful, harder to maintain server implementation with some of the benefits of GraphQL. It is a good and fast start for a migration though..

Wait, WHAT!?

A lot of time and energy spent by smart consultants to write those articles, read those articles, while most of them are finished with the “it depends on your use case” summary, without actually specifying those use cases!

I’ve been working with REST, GraphQL and SOAP APIs for many years. So I thought, why not come up with a list of those use cases and for each one of those to check — what can’t you do in GraphQL that you can do with REST and what you wouldn’t want to do with GraphQL and you would prefer REST.

After creating that list, I suddenly had a thought — what if there was another option — what if my powerful GraphQL server could just generate a REST API for me?

Then I could get the best of both worlds!

The more I dived into the idea and implementation then more I realized it’s not only that we can have both types of APIs created for us, but even if we just want to expose REST APIs, and none of our clients use GraphQL, GraphQL is the best way the create REST APIs!

How does the above sentence even make sense?!

That’s why those newly generated REST APIs get a lot of the features and benefits from the internal GraphQL implementation that make backend developers happy:

  • Fully generated documentation that is always up-to-date (Swagger, OpenAPI and GraphiQL)
  • Truly RESTful API out of the box
  • GraphQL Subscriptions as Webhooks
  • Runtime validation of data — be 100% sure that fetched data matches schema’s and query’s structure. You send exactly what I want to send, string is a string, an object has exactly the same properties.
  • Creating a custom endpoint is now a matter of choose a route name and attaching a query to it. done. No more manual work of creating and maintaining client specific endpoints!
  • Use GraphQL’s philosophy of evolving APIs through schemas — no more painful V1 — V2 API migrations.
  • Use modern technology that is easier to hire people to. Companies like Facebook, Airbnb and others have moved to GraphQL. None of them has gone back.
  • The power of GraphQL resolvers to create your API implementation, instead of manually written controllers from MVC

What I get from having resolvers?

  • Easier to transform data so it matches the response (GraphQL Schema). That’s because every entity has its own resolvers, so the mapping is moved into smaller pieces and reused across an entire app.
  • GraphQL allows you to easily share data across every resolver, we call it Context.
  • Forces you to define and resolve data in an opinionated way that actually helps building an API. It runs functions in parallel (functions that are nested at the same level), handles async and at the end, it is responsible of merging all of that into a single object, so you don’t have to think about it.

Sofa — Use GraphQL to create RESTful APIs

“How to” tutorial

Step 1: npm install the `sofa-api` package and add the following line of code:

Step 2: Go REST on a Sofa, you’re done.

Kamil Kisiela added Sofa to the SpaceX GraphQL API implementation by Carlos Rufo, in a single commit.

Check out the fully generated REST endpoints, the Swagger live documentation, GraphiQL editor and the GraphiQL-Explorer!

By the way, what you see here is a REST API, generated on top of a GraphQL API, created on top of another REST API….

Why did you do that for!?!?

Gradually migrating from old REST implementations

But those REST implementations are problematic (for all the obvious reasons people choose to move to GraphQL).

So our way to go is to create GraphQL implementations on top of those REST layers, migrate the clients to those implementations and then gradually remove the old RESTful layer and call the services directly.

Using Sofa made those transitions much faster because we can offer all the existing clients to migrate to our GraphQL implementation without actually using GraphQL themselves. We simply expose the same REST endpoints on top of GraphQL and they are moving to our layer happily because we can accommodate all of their requests and custom REST endpoints much faster than the original, old REST implementations.

Give me more details

Head over to the Sofa website for documentation and to the Github repository for reporting issues and helping out.

How Sofa works?

Sofa uses GraphQL’s AST to create an operation with all possible variables (even those deeply nested) and knows exactly what to fetch. Later on it converts the request’s body into operation’s variables and execute it against the Schema. It happens locally, but it’s also possible to use an external GraphQL Server or even Apollo Link.

Right now Sofa has a built-in support for Express but it’s totally possible to use a different framework. The main concept stays exactly the same so only the way we handle the request differs across different server implementations.

GraphQL Subscriptions as Webhooks?

Models / Resources?

type Query {
user(id: ID!): User
users: [User]

Before Sofa creates the routes, it looks for those Models and registers them so when the operations are built you don’t fetch everything but only an id.

But what if you want to fetch an entire object but only in few places?

There’s an option called ignore that allows you to do that. You simply pass a path in which you want to overwrite the default behavior.

Given the schema below, you would get just author’s id.

type Book {
id: ID
title: String!
author: User!
extend type Query {
book(id: ID!): Book
books: [Book]

With ignore: ['']you end up with an entire User object.

ignore: [''],

Swagger and OpenAPI


Stop wasting your life arguing about REST vs GraphQL — Be productive, get the benefits of both worlds and move into the future of API development.

I hope this would become the last REST vs. GraphQL article out there…. if you think it won’t, comment with a use case and let’s try it out!

Thanks to Kamil Kisiela for working with me on this and making this library a reality!

Follow us on GitHub and Medium, we are planning to release many more posts in the next couple of weeks about what we’ve learned using GraphQL in recent years.

The Guild

The Guild