AWS: Appsync the new BFF- Part 1

Arjun Sunil Kumar
Cloud Engineering
Published in
7 min readMay 30, 2020

--

Appsync

If you are here, most likely you have heard about GraphQL. Appysync is an AWS Service built on top of Appollo GraphQL implementation.

This will be a multipart series where I show you:

  1. Intro to Appsync & AWS configurations
  2. Subscription in Appsync
  3. Angular 7 app integrated to Appsync

Without further ado, let's get started!

What is BFF?

Backend for Frontend(BFF) is the single general frontline API layer (Fascade) which our clients would be communicating to instead of making multiple API calls to fragmented microservices. It can be thought of as Alexa. Using VI (Voice Interface), you ask Alexa to send an email, turn on light, play TV etc. Here Alexa is the BFF, and email service, TV service, Lighting service can be considered as microservices.

Realworld use case?

IoT Core + Appsync + Amplify

This use case is about an IoT based vehicle monitoring app. IoT sensor sends data to IoT Core, and trigger a lambda, with the received payload. The lambda invokes Appsync mutate endpoint and updates the sensor data. This data is saved into the data source (say DynamoDB). The data can be then subscribed by Mobile Apps authenticated via Cognito. This data can also be locally persisted (offline sync) for offline access.

Reference: Monitoring IoT devices in real-time with AWS AppSync

Appsync AWS Service

1. Schema

AWS Schema Tab

It defines the data attributes and functions available to the client.

1.a GraphQL Operations:

  1. Query (To read data from Database)
  2. Mutate (To update an entry)
  3. Subscribe (To subscribe to the changes introduced by mutating)

1.b Example Vehicle Schema

Note:

Vehicle Entity will also require Autoriziaton annotations. Else the below error is observed.

For Additional reference:

  1. AWS Docs
  2. GraphQL Docs

2. Resolvers

So you might be wondering how function declaration using type alone works in Appsync?

Resolvers Section

Function declarations have their implementations as well. On the right of Schema, we can see, the function declaration and we need to attach resolvers to the Query and Mutate functions.

For subscription, “@aws_subscribe” annotation alone does the job.

2.a Normal Resolver

  • A sample resolver implementation for CreateVehicle is shown below
createVehicle Resolver
  1. Data Resolver: Here we are DynamoDB data resolver.
  2. Request Mapping Template: Maps Data Request to DynamoDB PutItem.
  3. Response Mapping Template: It converts the response to JSON.

Note: The language used is Apache Velocity Template (AVT).

  • Similarly a sample resolver of Query:
getVehicle resolver

2.b Pipeline Resolver

Pipeline Resolver (Chain of functions)

You can also setup Pipeline Resolver. It is kind of a chain of actions that you can perform on a request, from multiple data-sources supported by Appsync. You can click on Convert to pipeline resolver link and it automatically sets up the chain of responsibility.

NOTE: You can also perform transformation alone using NONE Datasource functions.

Get + SNS Invoke Pipeline resolver

2.c Update Resolver for Single Argument (Used in subscription)

Normally, when you set up an AWS example, it provides UpdateVehicle endpoint which accepts the Vehicle Entity to be updated. In that case, it would be difficult to set up a subscription, based on a single argument (Say Id). So we need to set up a custom update function which accepts Id, latitude, longitude. So below is the data-source resolver for the same.

If you created/updated the schema manually, you can click on Create Resources button to create the corresponding DynamoDB tables etc.

3. DataSource

These can be used individually in schema functions or in conjunction with functions of pipeline resolver.

Below are the available Appsync data sources:

  1. AMAZON_DYNAMODB: The data source is an Amazon DynamoDB table
  2. AMAZON_ELASTICSEARCH: The data source is an Amazon Elasticsearch Service domain.
  3. AWS_LAMBDA: The data source is an AWS Lambda function.
  4. NONE: There is no data source. This type is used when you wish to invoke a GraphQL operation without connecting to a data source, such as performing data transformation with resolvers or triggering a subscription to be invoked from a mutation.
  5. HTTP: The data source is an HTTP endpoint.
  6. RELATIONAL_DATABASE: The data source is a relational database.

DynamoDB gets automatically created for the schema uploaded.

DynamoDB table holding Vehicle entity

For testing, I have created an SNS Lambda resolver, which just sends out a notification, when the endpoint is invoked.

3.a SNS Lambda

Below is the Node-based lambda, which sends SNS notification. This SNS Topic is having an email subscription.

3.a.1 NodeJS Serverless Code

3.a.2 IAM Role

Policies
Trust Relationship

4. Functions

Functions are single operations against a data source that can be used to implement redundant logic across multiple pipeline resolvers.

So, in the pipeline resolver, I can call a particular function and reduce redundancy. It is not applicable for regular data-source resolvers since they are having single function implementation.

Pipeline resolver & Functions

5. Queries

Here you can test your Appsync functions (Query, Mutation, Subscription).

If you have set authentication to Cognito, you will find a Login button on the top. Click login and provide the Cognito App client id, username and password.

Cognito App Client Id
Execute Appsync Command

Here you can see that function is placed in the first half, and argument values are placed in the second half.

5.a POSTMAN

You can also execute these GraphQL Queries from POSTMAN (Except for subscription).

Appsync + Postman

NOTE: I couldn’t get the Cognito Flow working in POSTMAN. But adding API-Key worked for me.

Execution Subscription request in POSTMAN will result in the below. The response is Amplify/Appsync specific, and postman won’t be able to process it. Subscribe works in AWS Amplify Queries, because of the embedded appsync SDK in there Query Page.

Subscription Response

6. Caching

You can enable caching on the responses from data-source.

7. Settings

You can find configurations like API URL, APP ID etc.

You can also set a primary authorization mode.

7.a Default authorization mode

You can configure Cognito Authentication. You can also provide App Client Id regex to provide access to only specific client ids in the User pool.

Cognito Auth mode

7.b Additional Authorization Provider

You can set up additional authorization providers like API key (That can be used in POSTMAN) etc.

7.c Logging

Enable logging to see logs in cloudwatch

Enable Logging

7.d IAM Role Permission

IAM policy for Appsync Log Role

7.e IAM Trust relationship

IAM trust relationship for Appsync Log Role

8. Monitoring

You can see cloudwatch metrics and logs if you have enabled Cloudwatch in the settings.

When you click on view Cloudwatch Logs, you will see the log messages. You can also use cloudwatch insight to make better use of logs.

Pros & Cons

Pros

  1. Offline Database for mobile/web client
  2. Realtime Update
  3. Fargate based (no worries about scaling)
  4. Internal throttling to protect against abusive traffic.
  5. Amplify support for Android, iOS, ReactNative (Flutter not officially supported)
  6. Authentications: IAM, Cognito, OpenID, API Key
  7. GraphQL benefits (Query what you need)

Cons

  1. Not that flexible for complex scenarios ( GraphQL replaces your entire BFF)
  2. The learning curve for Apache Velocity Template
  3. Exposed using Cloudfront (Hence no direct solution for monetisation, supported by API-Gateway or Apigee)
  4. No circuit breakers can be introduced.
  5. No developer portal available (as in API Gateway)
  6. Supported resolvers don’t include gRPC etc.

Conclusion

I have covered general details about Appsync. Next session would be about some insights on Appsync Subscription.

Found it Interesting?
Please show your support by 👏.

--

--

Arjun Sunil Kumar
Cloud Engineering

Writes on Database Kernel, Distributed Systems, Cloud Technology, Data Engineering & SDE Paradigm. github.com/arjunsk