Published on

Serverless GraphQL

Authors

I have been working with two bleeding edge projects, GraphQL and Serverless. Recently, it occurred to me that they might work well together, offering an infinitely scalable deployment of an amazing query language and runtime.

I thought, "I wonder if graphql-js would work as an AWS Lambda function?". Sure enough; it did.

Development and Deployment whoas

I typically approach a project with a number of things in mind. What are the frontend, backend and scalablity requirements. Planning for success, often the scalable pieces of the project grow more difficult with each iteration. Load balancers, master-slave database setups, job queues, caching layers. It adds up. Quickly.

I've been searching for a way to allow more focus on the project itself rather than managing the scalable pieces.

In 2014, Amazon announced AWS Lambda. The possibilities were endless, but I couldn't get past the need to interact with the service via manually uploading a zip file with my code. Fast forward to the summer of 2015 when the JAWS framework (now Serverless) was announced! Finally a way to interact with Lambda and other AWS offerings straight from the command line.

Serverless

"Serverless is an open source application framework for building serverless web, mobile and IoT applications exclusively on AWS Lambda."

It offers a command line abstraction of AWS resources. This includes CloudFormation, API Gateway and Lambda services along with the overall orchestration of these resources.

The Serverless CLI makes the process of intializing and interacting with your project extremely smooth with a command line driven approach to creating the scaffolding and additional resources. Deployment of your Lambda functions and API Gateway endpoints are quick and completely abstracted. Issue a command to deploy and a few seconds later you're able to interact with them.

Furthermore, you pay only when your Lambda functions and API Gateway endpoints are used.

GraphQL

With GraphQL, the query is the center of attention. Sure, there are types and schemas, but in my opinion, it's all about the query.

"GraphQL queries declaratively describe what data the issuer wishes to fetch from whoever is fulfilling the GraphQL query." -- graqhql.org

These queries allows clients to request and receive the exact data they need. This allows Facebook to support over 1,000 versions of their mobile applications without out the need to modify their backend.

Since it's release in the summer of 2015, GraphQL has grown on me as the preferred interface I would like to have from a frontend perspective. It allows my clients the ability to query for exactly the data they need, including nested data, and eliminate the need for addtional requests and data overfetching.

Simply put, it's a dream to work with.

Instead of adding new endpoints, application logic and database queries, I simply define or update GraphQL types and schemas, populate the resolve() function's to the data source (database query or Ajax call if the data is kept in another system) and deploy.

GraphQL is delivered via a single enpoint /graphql I knew that this would be the perfect candidate to run as a Lambda function.

Implementation

I decided that the perfect test of the idea, one that would allow enough nested data without too much complexity would be a Blog.

From conception of the idea of Serverless GraphQL a few weeks ago, to the reference implementation of Serverless GraphQL Blog I have spent less than $1 on AWS resources and only a few hours implementing.

I was able to generate my project, component, module and function in a few commands. Serverless offers these "four tiers of organization" for each project to allow for reusable pieces of code.

Iteration was quick and easy in that I'm able to use my favorite editor (Vim) to edit code and serverless dash deploy to deploy my Lambda function and API Gateway Endpoint into my development stage.

Given that Serverless orchestrates CloudFormation templates, I was able to define DynamoDB tables for the Post, Author and Comment types and they are automatically created with the proper permissions when issuing a serverless resources deploy. This was all achieved in the s-project.json

I was able to keep my GraphQL schema and DynamoDB interactions in a resusable /lib directory and only expose a single function (runGraphQL) to Lambda. This code could (and should) be unit tested separate from Serverless, since it is just JavaScript.

Reusability

What's ingenious is that with a recent release of Serverless, they have made other Serverless Projects installable into either a new Serverless Project or into an existing Serverless Project! Even the serverless-starter project can be setup with two simple commands npm install serverless -g and serverless project install serverless-starter.

This means, my reference implementation of a Serverless GraphQL Blog is installable with a single command serverless project install serverless-graphql-blog.

Heck, I can generalize this implementation into a serverless-graphql-api project and when the need arises in another project for a GraphQL instance, installing that project will instantly provide the scaffolding needed.

The Road Ahead

What started out as a crazy "what if?" has turned into a new direction for apps I plan to build in the future. Now that I'm able to use GraphQL in the most scalable and cost effective way possible, I'm certain that the days of deploying DigitalOcean servers are in the rearview mirror.

Apps that were previously 10's and 100's of endpoints are now possible with a single endpoint running GraphQL via Serverless on AWS Lambda.

Frontends can be published on S3. CORS support is already available for Serverless resources. Authentication via a custom Lambda endpoint (or Amazon Cognito, Auth0, etc). The pieces of a serverless architecture are starting to take shape.

The future looks mighty scalable.