No other language manifests Edsger Djikstra notion of brevity without jargon better than GraphQL. This is a querying language that has proven its worth by its simplicity and effortlessness in an application of what would otherwise be heavy and ugly in the domain of API calls and database querying. As I was exploring the capabilities of this querying language, I was quick to realize its potential in its main use as an API building tool. I also realized that its benefits are greatly underrated, and thus made it my aim with this piece to stress on the advantages of GraphQL as well as introduce its importance in the realm of serverless which is greatly aided by AWS AppSync.
AWS AppSync itself is a powerful application development service that allows you to create services using GraphQL. It truly does justice to the abilities of GraphQL and after personally using it to build a simple API, I can not imagine developing API’s with a serverless framework in any other way. Released in 2017, AppSync has several features that ease the use of GraphQL and again, I strongly feel that the value of these features is greatly underrated or simply not known due to the novelty of the service.
Therefore, considering the applications of AWS AppSync and its GraphQL support, I would not like to present a tutorial but rather an informative piece highlighting some of the many benefits that the ecosystem of software can gain by using AWS AppSync. This is because, just as in any ecosystem, where there exists an assortment of fruits to pluck from and there is always one fruit declared king of fruits, AppSync for me is the king of API support tools.
Before we dive into AppySync, we must first understand what GraphQL exactly is. What is this language whose beauty and power I have been incessantly ranting about for so long now? Well, GraphQL is basically a syntax that allows you to define what data you exactly need. It has three major components which include:
Schemas, which are the definitions of all operations
Data Sources, from where the data is queried
Resolvers, which act as connecting blocks between the schema operations and data sources.
The structure of GraphQL thus make it client-specific and thus allows the client to decide the data it needs instead of being bombarded with all kinds of data, irrespective of its relevance. This also leads to the substantial reduction of endpoints needed when building your API.
For example, let us say there is a database system for all the animals in the nation of Zambia, spread across the districts of the country. Yes, this probably is the most random example but we are sticking to it. We would like to query a district and get all the animals in the district. As can be expected we have an "Animal" table and a "Reserve" table, with many "animal"s to a single "reserve" relationship. If we were to query this using an API built with conventional methods, we would expect several HTTP calls procuring related data respectively. However, with GraphQL we can build a single endpoint which in turn acquires all the data with one call, and structuring the result in JSON format as shown in the image below:
From this example itself, the benefits of GraphQL start to become apparent and three main benefits that can be pointed out are as follows:
Refined Data Retrieval
GraphQL solves the problem of overfetching and underfetching and instead returns the exact data that is specified. A nice example of manipulating data with GraphQL can be seen here. Instead of making additional calls to retrieve each `animal` entity related to the `reserve` entity, GraphQL conducts the query in a single request. Moreover, the data returned is exactly as is defined, so for example, if we only wanted the list of animals in the animal reserve and not the area size of the animal reserve, the returned result would not contain the area size and hence make querying for data overall more efficient. This can also be seen to give more control to the client, allowing it to dictate exactly what data is required and how it is required.
Due to the GraphQL schema, the operations to be performed are defined comprehensively, all the way from the inputs to expected to the possible outputs. The strongly typed attribute of GraphQL schemas, in turn, ushers a wider range of benefits for developers such as making it easier to validate API requests, auto-complete in IDEs and auto-generation of API docs. As a result, the entire system attains a more pulchritudinous form allowing better understanding and ease of development, something not fully conceivable with traditional API development methods.
Since the way we perform operational requests to a GraphQL API necessitates defining the data returned, developers know exactly what the structure of the returned result is. Moreover, when we describe the GraphQL schema, we state the datatypes of all the fields used in the API operations and thus know what type of data is expected. All of this information aids in the development and use of the API, resulting in more efficient and productive product building.
Apart from the three benefits listed above, there are countless other advantages that I love and have personally gained with GraphQL. As much as I would like to list them all, there are only so many words I can write before I lose you to a random cat video. Ergo, I strongly urge everyone intending to build data-driven applications to checkout GraphQL as to experience its simplicity and power firsthand.
On the 13th of April 2018, AWS made AWS AppSync generally available (GA), ushering in an era of improved GraphQL support. As I already discussed, the exceptional benefits of GraphQL endorse its use in the field of data-driven development and hence with AppSync, AWS has managed to make GraphQL development incredibly easy and accessible. AppSync has proven effective as a development tool due to its powerful features and simple set-up, the two qualities of every developer's dream tool.
AWS describes AWS AppSync as a “serverless back-end for mobile, web, and enterprise applications”. Considering the pure definition, Amazon has continuously released features over the past two years to facilitate AppSync’s role as a serverless service for data-driven applications. Recently, at Amazon’s AWS re:Invent 2018, AWS software developer engineer Karthik Saligrama described two new features which AWS was adding under the hood of the AppSync service. One of the features includes support for Aurora Serverless through automatic resolvers, and the second is pipeline resolvers which facilitate more complex GraphQL operations. These two features are now among countless other features, all easing the support of data-driven development and promoting the use of GraphQL. Apart from the two features already mentioned above, I would like to list out other basic features that I believe deserve a mention.
Effortless Development with Code Gen.
The guys at AWS have put a lot of stress on making development with AppSync child’s play, and this is apparent with the code generation capabilities that AppSync provides. This involves acquiring automatically generated schemas and resolvers, mitigating the pains of having to define even the simplest of operations manually.
Automatic code generation is offered in two forms. One of them can be done via the AppSync Management console and the other is done using the AWS Amplify CLI.
The AWS management console provides several opportunities for you to benefit from the automatic code generation feature. For example, when creating a data source, you can choose to create a DynamoDB data source automatically which will also give you the option to generate automatic schema code. Similarly, you can also use the aided API building option which comes up as you start development of your application.
Similarly, you can generate schema code and even resolvers using the AWS Amplify CLI.
The end result is an automatically generated API with all client-side operations already present and ready for use. This truly is a boon for developers as it allows for faster code development and a more structured approach to building data-driven applications.
From my personal experience, I can honestly say that the most complicated component of GraphQL is configuring the resolvers. There are many ways to achieve the same task depending on the operation being performed by the resolver. With AppSync’s resolver utilities, you are given a template of various operations which you can use and build upon. Some templates can even be used as they are and do not need any editing. Moreover, the templates themselves change according to the data source that is being used presenting the comprehensive support that AppSync provides.
The templates themselves cover a range of operations from simple ones such as to get an item by "ID", to retrieving all the data items that were created on the current day. All other possible operations that would be required can then be built around these templates.
Cloud Formation Support
AWS Cloud Formation allows you to manage your AWS stack and manage your AWS resources via templates. The way it is used is you defining the resources you would like in a yaml or json file and by deploying the service either using serverless or through the CloudFormation console, AWS generates the resources and makes them ready for use as you specified.
Cloud Formation templates now support AppSync and hence setting up your data-driven application architecture has now become easier. This means that schema operations, data sources and the resolvers to connect them can all be defined using the Cloud Formation template. To learn how to do so, please follow the tutorial here.
Fine-Grained Authorization and Access
Fine-grained access means controlling the manner in which data can be read or write depending on the authorizations that the clients possess. This allows you to define various security configurations for different data resources according to user identity, conditions and data injections. Hence providing flexibility in how the data sources within your AWS are managed.
The way this is possible is thanks to the fact that AppSync adds user and role information into the GraphQL request as a context object. This object can then be accessed by the resolver to grant permissions within the resolver logic. Deciding whether or not to give permissions is as easy as writing a single `if` statement. More complex authorization logic can obviously be written, and to fully understand how to do so, you may refer to the AWS documentation here.
Therefore, considering the benefits of GraphQL coupled with the features of AppSync, I truly believe that Amazon has revolutionized the way data-driven applications are being developed. There are obviously pros and cons to the case, but from my experience, I would strongly recommend everyone to become accustomed to GraphQL. AWS AppSync is still a relatively new tool, but we shall not be wrong to expect new features to continuously role in.
In these concluding lines, I would like to state that in this piece I have mentioned only some of the benefits of GraphQL with AppSync. AWS AppSync boasts a myriad number of advantages for any developer who decides to pick up the tool. The animal demo that I used can be found on my GitHub here. This piece shall be continued with another demonstrating how to build a sample project.