Azure Function + GraphQL + Azure Cosmos DB = Serverless Goodness
A GraphQL schema generated using GraphQL CLI via an endpoint.

Azure Function + GraphQL + Azure Cosmos DB = Serverless Goodness

The cloud brings about many important innovations including the concept of serverless. This concept allows businesses to write applications that will execute and scale on-demand, thus effectively managing resource consumption and hence brings down cost.

Azure Function is the face of serverless in the world of Azure. Azure Function includes many types of triggers including the HTTP trigger. This means we can write RESTful APIs that can be consumed and scaled on-demand. The Azure Function SDK also makes it easy to tie in Functions with Cosmos DB, which we can be ensured of high availability, and disaster recovery, compared to traditional options where we have to manage those concerns. However, this also means having to write multiple Azure Functions to represent each RESTful resources - which can eventually become unmanageable in the long run. Documentation for each of the RESTful endpoint can also become unwieldy as our list of API grows. This is where GraphQL may be able to help.

GraphQL has been around for the last couple of years and has gain much momentum in the community due to its powerful capabilities. GraphQL is a standard which developers can leverage to expose their data schema where consumers can use to query for, and manage data. GraphQL also comes with a rich set of community sponsored tooling like GraphQL CLI to help consumers.

To compare and contrast with REST, let's use an example. Let's assume we have a RESTful endpoint to manage a resource called BookReviews. Traditionally, by RESTful conventions, we would create 4 HTTP verbs to support the BookReview resource. A POST to create a book, a PUT with an Id as part of the route to update a BookReview resource, a DELETE with an Id as part of the route to delete an existing BookReview resource, and a GET to get a BookReview by Id or whatever query string parameters is exposed to query for one or more books.

With GraphQL, we may have a single HTTP endpoint (with GET and POST verbs supported) which is typically a generic endpoint to manage more than one resource. This means that on a high level, all consumers know to use that single endpoint and don't have to assume or know about any additional endpoints. This single endpoint will expose a schema that consumers can query for ahead of time to figure out the capabilities/API. This is seen as part of the screenshot. As part of the schema, we, as developers of the API can expose exactly what consumers can do to manage BookReview. More than that, we can give consumers the power of how they intend to query for BookReviews.

The following is an example of how a query can be constructed. The schema informs the consumer of an API named getBookReviewsWithBookNameAndCategory which is exposed and that they can query by 5 different query parameters with comparisons as options. We can define which fields are returned. In fact, we can also selectively return associated entities such as book and reviewer and define which particular fields from those entities we want returned since the schema allows for it - in this particular case. Each consumer may have different data requirements but they can make different decision on what data they want and are not forced into a single set of data construct.

query{
  getBookReviewsWithBookNameAndCategory(
    name: {equal:"FOO"}, 
    category:{contains:"BAR"}, 
    writtenon:{ greaterThan:"2018-01-01"},
    stars:{equal:5},
    active:{equal:true}){
    id
    book{
      id
      name
    }
    comments
    reviewer{
      name
      region
      interests
    }
  }
}

On the backend, GraphQL has the concept of resolver to bring data back from the various types of repositories. We, as developers can write our own resolvers or use a predefined one from an existing GraphQL framework - which there are many. Resolvers has the ability to translate the GraphQL query into the repository specific language/ syntax and perform the actual query. This is one of the many powerful capabilities of the GraphQL standard. GraphQL has additional specifications for caching, paging etc. If you are excited about the possibilities and want to start playing with GraphQL, there are many frameworks out there today that we can leverage to build our own GraphQL server.

With these ideas in mind, I started googling for a Azure specific GraphQL solution. Specifically, I am interested in leveraging GraphQL in the context of a serverless option in Azure, given the benefits of serverless mentioned earlier. Looking around, I did not find too many options. This is why I started an open source Azure specific project to achieve this based on an existing implementation, graphql-dotnet. What I did was to tie it in with Azure HTTP Function and created specific revolvers for repositories such as Azure Cosmos DB. If you are interested to try it out, follow the links below.

Code: https://github.com/seekdavidlee/Eklee-Azure-Functions-GraphQl/

Nuget: https://www.nuget.org/packages/Eklee.Azure.Functions.GraphQl

I am excited about the future of how serverless concepts will continue to evolve and how ideas such as GraphQL can continue to play a key role in how we write APIs that consumers can easily leverage, bringing much value to businesses!

This is great in the Azure serverless world. Thanks for sharing.

Like
Reply

This looks great and is exactly what I'm looking for. In the documentation you talk about setting up the pointers to your documentdb in the mutations class, what happens if you're not using mutation just queries?

Really cool! Thanks for sharing.

To view or add a comment, sign in

More articles by Eng Keong (David) Lee

Others also viewed

Explore content categories