Accelerate your backend development using AWS + Serverless + GraphQL

Are you investigating what tech stack to choose for your next project? In this article I will guide you into the world of GraphQL and Serverless which I have been using for the latest months developing a SaaS product from scratch.

Introducing GraphQL

So what exactly is GraphQL? Since you are reading this article you probably know what REST is and GraphQL is here to replace it. Yes, you read it correctly. At first I was sceptical to exactly what the benefits of GraphQL were — it just looked like another way of writing regular API calls to me. However after using it for a while and seeing what it can do I am convinced it will be the new standard for developing app backends in the future. Comparing to a REST setup that typically has a large number of endpoints with different URLs and HTTP verbs GraphQL only has one endpoint using the HTTP POST verb. Through this single endpoint you can send two types of requests: queries and mutations.

Queries are typically used to get data just as you would using a HTTP GET request in a REST API. Below is an example of a GraphQL query:

query GetProject($id: String!) {
    getProject(id: $id) {
        id
        name
        description
    }
}

The outer wrapper of the GraphQL query defines the name and the input parameters. The inner wrapper defines the data you want to retrieve from the query — in this case we want to get the id, name and description of the project that we are retrieving from our database. The input parameters to a query are defined separately as regular JSON. In this case the parameters could be:

{
    “id”: “4ad81e4d-4e99–4e3b-b3d0–5061e2fd367c”
}

A response for this query could look something like this:

{
    “data”: {
        “getProject”: {
            “id”: “4ad81e4d-4e99–4e3b-b3d0–5061e2fd367c”,
            “name”: “Boogle”,
            “description”: “Your next door potential unicorn startup.”,
        }
    }
    “errors”: []
}

The property data not surprisingly contains the data returned from the query. As you can see the data object also has a getProject property that contains the project we are looking for. This might not look that clean to you but this enables you to fire multiple GraphQL queries in one HTTP call. The data for each query will then be appended to the data object in the response. This saves you the overhead of having to make multiple HTTP calls to get the data you need in the client. There is also a property called errors — this is used if anything goes wrong during your request. In this case the array is empty but let’s say the database connection failed while the project was being fetched. Then an error would be appended to the error array and the frontend could display an error accordingly. No more checking for different HTTP status codes and tailoring your own error handling standard.

Another advantage of GraphQL is that you can include related data easily with a query. Let’s say that we want to get all of the tasks related to a project. Then we would simply use a query like:

query GetProject($id: String!) {
    getProject(id: $id) {
        id
        name
        description
        tasks {
            name
        }
    }
}

This will give us all of the tasks for the project including the name for each task. Using REST this would typically be done with multiple HTTP calls which results in more time spent making the requests and custom logic to fetch the related data.

Moving on to mutations. Mutations are used to manipulate data — things that would typically be done with a POST, PUT or DELETE request using a REST API. In the mutation example below we are going to create a project. Since the input will be an object we want to define a custom type so that GraphQL can validate it as soon as the request hits our GraphQL endpoint. This is how we might define a Project type in our example:

type Project {
    id: String!
    name: String!
    description: String
}

This type definition will validate that all of the attributes are strings. The exclamation mark after the String in the id and name parameters means these parameters will not accept null.

OK — now we have a type called Project. Let’s use it in out mutation:

mutation CreateProject($project: Project!) {
    createProject(project: $project) {
        id
    }
}

With the parameters:

{
    “project”: {
        “name”: “Yoogle”,
        “description”: “Forget Boogle — Yoogle is here!”
    }
}

And the response:

{
    “id”: “a63f9e40–0a0b-40fa-8359–484f4cfe5962”
}

As you can see we can decide which data to include in the response just as we did using a query.

Introducing Serverless

OK. Now you know the basics of GraphQL. So how do we deploy our GraphQL backend? This is where Serverless and AWS comes in. Serverless is a technology that enables you to focus 100% of your time on writing code instead of thinking about provisioning, maintaining and configuring servers. AWS (or another cloud provider with support for Serverless 😉) takes care of the provisioning, maintenance, configuration and scaling of the infrastructure that your code runs on behind the scenes.

The Serverless offering from AWS is called Lambda. Using Lambda we can run our GraphQL backend with ease. Lambda is charged for each 100 ms that your code runs and you get 1 million requests for free each month — perfect when you are just getting started on a project. Compared to provisioning a dedicated VM or container cluster to run your backend this will save you hundreds of dollars and many hours of work for each deployment of your backend. Lambda currently has support for the following programming languages with more on the way:

  • Java
  • Go
  • PowerShell
  • Node.js
  • C#
  • Python
  • Ruby

There are also several frameworks that can be used to help you with the deployment and development of your GraphQL backend. One of more mature frameworks that I can personally recommend is called Serverless Framework (https://serverless.com) which boasts a huge community with loads of plugins and great support.

Using Serverless Framework defining an API endpoint for your GraphQL API is done through a file called serverless.yml. A simple example could look something like below:

service: graphql-api
app: graphql-api
provider:
    name: aws
    runtime: nodejs8.10
    region: eu-west-1
functions:
    graphql:
        handler: graphql.handler
        events:
        - http:
            path: graphql
             method: post

This will create a Lambda function with the path /graphql which will respond to POST requests. The code for the Lambda is defined in the file called graphql.js which is pointed out as the handler attribute for the graphql function. This handler function will be the single point of entry into our backend which will take the GraphQL-query in the request, execute our application logic and from that create a GraphQL response. Here is an example of a GraphQL handler function written in Node.js and using the GraphQL library Apollo (https://www.apollographql.com):

import express from ‘express’;
import serverless from ‘serverless-http’;
import { ApolloServer } from ‘apollo-server-express’;
import { makeExecutableSchema } from ‘graphql-tools’;
import types from ‘../types’;
import resolvers from ‘../resolvers’;
const app = express();
const server = new ApolloServer({
    schema: makeExecutableSchema({
    types,
    resolvers
    }),
    path: ‘/graphql’
});
server.applyMiddleware({ app });
export const handler = serverless(app);

So how do we deploy this code from our local serverless.yml file to an API serving HTTP requests in AWS? Simple. There is only one command needed to deploy the entire backend to our virtually infinitely scalable fully managed infrastructure:

serverless deploy

This will package all of your code, upload it to S3 (a static file storage service in AWS) and create a Lambda function that points to the code in S3. The Lambda is then connected to an API Gateway that enables it to respond to HTTP requests. As your code grows however you will probably need more commands to handle different deployment steps such as database migrations, running tests etc but this is a very neat way of deploying your code to a live environment straight from your command line.

Get started!

So — I assume you are now fully convinced that GraphQL and Serverless is the right way to go for your next project? 😃

If you want to get started using Serverless and GraphQL I recommend the following guide for the basics on Serverless: https://serverless-stack.com. It provides a thorough explanation of Serverless and everything you need to get a backend and frontend running on AWS as well as hands on experience with a couple of other AWS services.

For GraphQL I recommend the aforementioned Apollo GraphQL Platform which provides great tools for both backend and frontend. For more information on the basics about GraphQL the official documentation at https://graphql.org/ is very well written.

That is it for this time! Please feel free to connect with me on LinkedIn if you want to discuss your next project or anything else regarding AWS 🚀