With all the madness currently going in the API world with GraphQL, you might be wondering how to migrate your existing REST APIs to GraphQL without breaking anything. This guide will help you accomplish your REST to GraphQL mission without changing your codebase so that you can REST with GraphQL! (pun intended 🤭)

REST to GraphQL

Well, GraphQL advocates have done a great job in marketing GraphQL already. Respecting their efforts, I won’t be going into details, but provide a summary:

  • GraphQL allows you to fetch multiple resources in a single request.
  • GraphQL solves the over fetching problem of REST by letting you describe your exact data needs.
  • GraphQL helps you solve the N+1 query problem on frontend by fetching related data in a single query.

What I will be touching upon in this guide instead is the aspect that most people miss while advocating GraphQL, which is, “We have already invested heavily in REST”. This means:

  • Most of our existing services are in REST.
  • We are more comfortable writing REST services.
  • We want to support existing clients using REST APIs.

While many articles help you migrate from REST to GraphQL, they all force you to change your existing codebase or write a new one in front of your REST services.

But wait…

If it works, then don’t touch it.

Wasn’t this the first rule of programming?

Migrations can be painful, especially the magnitude of a huge codebase can be daunting. There is always a chance of breaking something.

Why can’t we just REST?

Let’s face the fact - We all are lazy by nature. We love simple hacks and easy solutions.

What if there was a way wherein you could keep your REST services as is and still get a GraphQL layer on top of it without writing any code whatsoever? Sounds like a magic right? Well, Space Cloud helps make this possible.

What is Space Cloud?

To keep things simple,

Space Cloud is an open-source web server which provides instant GraphQL and REST APIs on your database and microservices.

The coolest part about Space Cloud is that all the APIs are realtime. You can optionally subscribe to changes in the database. This functionality comes in handy while making real-time apps.

However, in this guide, we will stick to Space Cloud’s remote service module to migrate your REST services to GraphQL.

Like it already? Show your support ❤️ by giving us a star on Github.

The architecture

This is what the final architecture of GraphQL over REST looks like:

Rest services with Space Cloud

Your apps make a GraphQL query to Space Cloud, which in turn hits a REST endpoint on your server. Space Cloud acts as a GraphQL proxy or API gateway in this case.

As you would have noticed, Space Cloud is a separate GraphQL layer that sits on top of your REST services. The beauty of this fact is that your REST services are still intact, and you can use them directly in your existing clients. This fact lets you ship your REST service to GraphQL without breaking your older clients.

Great! We have understood what Space Cloud is and how it sits with our application. Let’s get straight to some action!

What we will be building

In this guide, we will be building a simple arithmetic service which has the following endpoints:

  • Adder endpoint: POST /adder
  • Doubler endpoint: GET /doubler/:num

The adder endpoint will return the sum of two numbers that it gets from the request body. The doubler endpoint, on the other hand, will return double of the number that it receives as the URL path parameter.

Great! Let’s start building things now!

Note: Don’t worry if you get stuck somewhere. You can always ping me on this Discord server, and I will help you out personally.

Step 1: Writing a service

Note: Even if you are reading this from your mobile right now, you can still follow this guide along just by reading.

Let’s start by writing our REST service. We are going to write our REST service in NodeJS using Express.

Note: You can write your service in any language or framework as long as it can speak HTTP since that’s the protocol Space Cloud is going to use to communicate with your REST service.

First, create a folder that serves as our working directory.

Create NPM project:

npm init -y

Install Express:

npm install --save express

Write express server

Create a file index.js and copy paste the following code:

var express = require("express");
var app = express();

app.use(express.json());

app.post("/adder", function(req, res) {
  const num1 = req.body.num1;
  const num2 = req.body.num2;
  const response = { result: num1 + num2 };
  res.status(200).send(JSON.stringify(response));
});

app.get("/doubler/:num", function(req, res) {
  const num = req.params.num;
  const response = { result: num * 2 };
  res.status(200).send(JSON.stringify(response));
});

var server = app.listen(5000, function () {
    console.log("app running on port:", server.address().port);
});

As you can see, the code is pretty straight forward. We have just created an HTTP server using ExpressJS that is listening on port 5000.

The server has two endpoints, as we discussed earlier:

  • Adder endpoint: We are expecting to receive two numbers - num1 and num2 from the POST body. All we are doing is returning the sum of these two numbers.
  • Doubler endpoint: We are simply returning the number that we are getting from the URL path parameter.

That’s all we need to write for this service.

Note: For migrating your existing REST services, you don’t need to write/modify any code. And if your services are already running, you can skip the next step.

Step 2: Start the service

Simply run the following command to run the service:

node index.js

Great! We have our REST service up and running. Let’s start Space Cloud and use this REST service via GraphQL.

Step 3: Download Space Cloud

You need to download the Space Cloud binary for your operating system, or you could build it directly from its source code. You need to have go version 1.13.0 or later to build it from source.

Download the binary for your OS from here:

You can unzip the compressed archive.

For Linux / Mac: unzip space-cloud.zip && chmod +x space-cloud

For Windows: Right-click on the archive and select extract here.

To make sure if the binary is correct, type the following command from the directory where the binary is downloaded:

For Linux / Mac: ./space-cloud -v

For Windows: space-cloud.exe -v

It should show something like this:

space-cloud-ee version 0.13.0

Step 4: Start Space Cloud

To start Space Cloud in dev mode, copy-paste the following command and hit enter:

For Linux / Mac: ./space-cloud run --dev

For Windows: space-cloud.exe run --dev

You should see something like this when Space Cloud starts:

Creating a new server with id auto-1T5fA9E1B2jeNUbV8R0fOPubRng
Starting http server on port: 4122

   Hosting mission control on http://localhost:4122/mission-control/

Space cloud is running on the specified ports :D

Note: The --dev flag tells Space Cloud to run in dev mode (so that the admin UI does not ask for a username and password)

Step 5: Configure Space Cloud

As you would have noticed, Space Cloud generates a config.yaml file in the working directory.

Space Cloud needs this config file to function. The config file is used to load information like the REST servers to connect to and their endpoints.

Space Cloud has it’s own Mission Control (admin UI) to configure all of this quickly.

Open Mission Control

Head over to http://localhost:4122/mission-control to open Mission Control.

Note: Replace localhost with the address of your Space Cloud if you are not running it locally.

Create project

Click on Create a Project button to open the following screen:

Create a project screen

Give a name to your project.

It doesn’t matter which database you choose here since we won’t be using it anyways.

Hit Next to create the project.

Step 6: Add remote service to Space Cloud

Head to the Remote Services section in Mission Control.

Click on the Add first remote service button to open the following form:

Add service screen

Put the service name as arithmetic and service URL as:

http://localhost:5000

Once you have added the remote service, you should be able to see it in the remote services table:

Services table

Click on the View button in the Actions column to open the service page.

Click on the Add first remote endpoint button to open the following form:

Add endpoint screen

Put the following adder endpoint:

  • Name: adder
  • Method: POST
  • Path: /adder

Once again click on the Add button to add the doubler endpoint as well:

  • Name: doubler
  • Method: GET
  • Path: /doubler/{args.num}

Note: Don’t worry about the {args.num} part now. Just make sure you have put the Method as GET.

Step 7: Query your REST service via GraphQL

We have added our REST service and the two endpoints as well to Space Cloud. Time to query it using our unified GraphQL API.

Head to the Explorer section:

Explorer

Try running the following GraphQL query in the GraphiQL explorer:

{
  adder(num1: 10, num2: 20) @arithmetic {
    result
  }
}

You should be able to see a response like this:

{
  "adder": {
    "result": 30
  }
}

On getting the above GraphQL query, Space Cloud had made the following request to your REST service:

  • Method: POST
  • Path: /adder
  • Request Body:
{
  "num1": 10,
  "num2": 20
}

This means the arguments that you pass in the GraphQL query are send as request body to your REST service.

Let’s try querying the doubler endpoint with the following GraphQL query:

{
  doubler(num: 50) @arithmetic {
    result
  }
}

This GraphQL query is translated by SC to a REST call as follow:

GET /doubler/50

If you remember the endpoint which we added to Space Cloud for doubler was:

/doubler/{args.num}

Based on this endpoint, Space Cloud understands that it has to pick an argument num from the GraphQL query and use it as a variable to form the path /doubler/50.

On successful invocation, you should be able to see a response like this:

{
  "doubler": {
    "result": 100
  }
}

Bonus - Service Chaining

Having followed this guide till here successfully, we all deserve a well-earned bonus! Let’s see how this REST to GraphQL transition unlocks a super awesome power, Service Chaining, for us.

Let’s take a scenario where:

  • We want to sum two numbers using the adder service.
  • Double the result we got from the adder service.

The REST way

If we were using REST in our client-side code, the above task would have looked like this:

REST way

Notice, how we are making two requests from the frontend which means twice the roundtrip time. It leads to a slow response time and poor user experience.

The GraphQL way

Now if we switched the client from REST to GraphQL using Space Cloud, our requests will look like this:

GraphQL way

Notice, here we are making only one GraphQL query from the frontend to the backend (Space Cloud). Space Cloud, in turn, is making two requests to your REST server to fulfil this request. However, the round trips of these requests (from Space Cloud to your server) are negligible as they are in the same network.

The GraphQL query to Space Cloud to achieve the above task will be:

{
  adder(num1: 10, num2: 20) @arithmetic {
    doubler(num: "adder.result") @arithmetic {
      result
    }
  }
}

Notice, how we are calling the doubler service after the response of adder service and passing the result of adder service to the doubler as an argument.

The response for this query will look like this:

{
  "adder": {
    "doubler": {
      "result": 60
    }
  }
}

As you would have guessed we got 60 as a result ((10 + 20) * 2).

Additional tip: If you wanted to query two unrelated REST services parallelly, you could have done that too in a single request like this:

{
  adder(num1: 10, num2: 20) @arithmetic {
    result
  }
  doubler(num: 50) @arithmetic {
    result
  }
}

I will leave the response part of this query to you as an assignment😛.

Conclusion

First of all, give yourself a pat on the back for having followed this guide to the end.

We learned that:

  • Migrating from REST to GraphQL doesn’t require code changes.
  • We don’t need to choose between REST and GraphQL. We can support both REST and GraphQL together in the same application.
  • Using GraphQL with Space Cloud provides us with some neat networking benefits and helps you reduce your round trips.

Well, there’s a lot more you can do with Space Cloud other than migrating from REST to GraphQL (eg: cross-database joins). Give Space Cloud a star on Github if you like it ❤️. Join our Discord server if you wanna bounce off some ideas or have any questions.