Eklee-Azure-Functions-GraphQl, A Serverless GraphQL implementation on Azure
GraphQL enables a powerful way of expressing queries, and mutations against one or more HTTP endpoints using HTTP verbs POST and GET. GraphQL also has a concept called subscription where consumers can choose to subscribe to events that they are interested in.
There are several GraphQL implementations that you can choose from, but all implementations follow the same GraphQL specifications. In this article, we are specifically referring to the implementation of Eklee-Azure-Functions-GraphQl. As a disclaimer, I am the author of said implementation and based on your platform of choice, I would like to suggest several considerations for using Eklee-Azure-Functions-GraphQl.
Before we proceed further, I would like to call out that Eklee-Azure-Functions-GraphQl uses GraphQL dotnet. This means Eklee-Azure-Functions-GraphQl is simply a wrapper around an existing open source GraphQL engine and does not itself implement (or needs to implement) any of the GraphQL specifications. It is all taken care of by GraphQL dotnet. In fact, you may even decide to use GraphQL dotnet directly after reading this article!
I would like to also call out that Eklee-Azure-Functions-GraphQl uses another library I have created — https://github.com/seekdavidlee/Eklee-Azure-Functions-Http. This library is used to help provide dependency injection support, logging, caching, security and other common needs. The dependency injection uses AutoFac as a requirement.
Cloud Native on Azure
The premise for leveraging Eklee-Azure-Functions-GraphQl is that it is specifically built for use in Azure in a cloud native fashion - which means we can have a cloud optimized solution for our GraphQL API. Thus, our first consideration of whether to use Eklee-Azure-Functions-GraphQl is that it will not work on other cloud platforms such as Google or AWS. There are other GraphQL engines that are supported on those cloud platforms. In fact, you may even consider using GraphQL dotnet as it is cloud agnostic and can run on PaaS offerings on those platforms.
Eklee-Azure-Functions-GraphQl is built on top of Azure Functions which means it is serverless. As such, we will not have the need or responsibility of managing scaling when we are on the consumption plan. We will be billed based on our consumption which could potentially mean cost savings in the long run (this is where Cloud excels!). Azure Functions sits on top of a PaaS service called Azure App Service which gives us the option to go with different plan type as needed based on our requirements.
Integration with Azure Services
GraphQL dotnet does not directly integrate with database sources, but it does offer a list of database sources that other developers have developed that can be used. In the world of GraphQL, this capability is known as resolver(s), which is the connector(s) that translate your GraphQL query inputs into database specific syntax with your back-end database sources.
Eklee-Azure-Functions-GraphQl attempts to bridge that gap with its own resolvers against the following Azure specific database sources:
- Azure Cosmos Db (SQL)
- Azure Search
- Azure Table Storage
In addition, Eklee-Azure-Functions-GraphQl supports both HTTP and in-memory database sources as well. However, it is recommended that the in-memory database source be used only for unit or integration testing purposes.
Multi-tenancy and Azure Active Directory
With support for the mentioned Azure database sources, we should note that Eklee-Azure-Functions-GraphQl does offer a multi-tenancy strategy built around Azure Active Directory (AAD) (for authentication and authorization). This means that we can secure our GraphQL API with JWT generated from AAD identity providers and recognize which identity provider the request is coming from i.e. tenant. Let’s review this behavior a little deeper.
With each request, whether a query or mutation, we have the ability to prevent unauthorized access by validating the HTTP request by inspecting the tenant specific JWT token. Once we are able to identity the tenant, we now have the ability to segregated our database sources physically (via different database or collection within a database in the case of Azure Cosmos Db for example) or by a key. This capability is achieved via the IJwtTokenValidatorParameters interface which is part of Eklee-Azure-Functions-Http.
If you have requirements to support other identity providers (other than AAD), note that it may not be supported. If you are curious about the implementation, you can refer to the following: https://github.com/seekdavidlee/Eklee-Azure-Functions-Http/blob/master/Eklee.Azure.Functions.Http/JwtTokenValidator.cs. As you can see in the code, we are using JwtSecurityTokenHandler from Microsoft.
Schema First VS Graph Type First Approach
GraphQL dotnet offers two different approaches to creating a GraphQL schema. Eklee-Azure-Functions-GraphQl uses the GraphType first approach in relation to creating queries and mutations schema.
To be clear, if you are interested in hosting your GraphQL API using Azure Functions, but would like to write your own resolver(s), then you can still use the Schema first approach. However, to leverage the resolver(s) we have built, we would need to use the Graph Type first approach which can provide type safety during compile time. It is also noted on GraphQL dotnet’s site that some advance scenarios may not be supported.
Queries, Mutations, and Subscriptions
Eklee-Azure-Functions-GraphQl implements support for queries and mutations. There are several extension methods available to drive the fluent syntax in establishing the schema as well as with the help of model attributes. In addition, if you are interested establishing relationship between models via an edge relationships, take a look at the following link which gives several examples of how to do this: https://github.com/seekdavidlee/Eklee-Azure-Functions-GraphQl/blob/master/Documentation/Connections.md.
As for subscriptions, other GraphQL implementations have been using websockets to help subscribers get notified of events. This includes GraphQL dotnet as well. However, Eklee-Azure-Functions-GraphQl uses Azure Functions which is code that is executed on demand. Thus, it is not possible to leverage websockets where connections are maintained.
It is not to say subscriptions cannot be implemented differently. As a note, there is no specific implementation details per the GraphQL specifications on how subscription can and should be implemented. Hence, I am looking into the possibility of using web hooks as an implementation possibility for subscriptions. In the short term, the quick answer is that subscription is not supported in case this is one of your use cases.
Hopefully, this article helps you make a decision of whether Eklee-Azure-Functions-GraphQl can be useful for your project and what to consider when using it. The key point here is that in an attempt to utilize cloud native capabilities, Eklee-Azure-Functions-GraphQl is built for Azure using Azure specific services. It would not work for other Cloud platforms.
If you are interested in an implementation example, please refer to the following github link: https://github.com/seekdavidlee/Eklee-Exams-Api. There are some complexities to set it up because we are also trying to demonstrate multi-tenancy. Suggestions on how to improve this will be much appreciated!
Feel free to reach out to me on the link for any questions or issues: https://github.com/seekdavidlee/Eklee-Azure-Functions-GraphQl/issues. Thank you!