# Notes on Serverless GraphQL with AWS AppSync

Original: https://swyx.io/serverless-graphql-appsync
Published: 2020-10-28

> My Notes on Slobodan Stojanovic's Serverless GraphQL with AppSync talk

[Slobodan Stojanovic](https://twitter.com/slobodan_/status/1321569045003513856?s=20) is an AWS Serverless Hero and released a well received, 30 minute talk on AWS AppSync today at ServerlessDays Virtual. I've given a (in my opinion) bad Serverless GraphQL talk before, I wanted to take notes on what a good one looked like.

Here is his talk (starts 1h 54mins in):

{% youtube 9oYS_5eL610 %}

Here are his [slides](https://speakerdeck.com/slobodan/the-power-of-serverless-graphql-with-appsync)

And here are my notes of his talk.

## Notes on AppSync

**Your requirements**:

- short deadline
- scalable
- real-time

### Why GraphQL

Standard origin story from Facebook/FQL. Why should you care if you are not Facebook?

If you have...

- Clients for multiple platforms (eg Web and Mobile) have different data requirements
- Backend serves data to clients from different sources
- Complex state and caching mgmt for both front/backend
- Slow mobile pages caused by HTTP waterfalls

Then you will benefit from GraphQL's properties:

- Defines a data shape
- Hierarchichal
- Strongly Typed
- Is just a protocol, doesnt prescribe storage
- Introspective
- Version free
- **Supports Queries, Mutations, Subscriptions**

### Why Serverless

So you dont need to manually scale/distribute the individual pieces of your GraphQL-gated backend.

### Why AppSync for Serverless GraphQL

You *could* write a GraphQL backend inside of API Gateway + AWS Lambda function... but it'd be a lot easier using AppSync.

The workflow then becomes: 

- Define GraphQL Schema
- Automatically Provision a DynamoDB data source and connect resolvers
- Write gql queries and mutations
- Connect with Frontend

### Why AWS Amplify with AWS AppSync

You *could* set up AppSync via the [Guided Schema Wizard](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html) on the AWS Web Console... but you should use Amplify, CloudFormation or CDK for [IaC](https://en.wikipedia.org/wiki/Infrastructure_as_code).

Amplify reduces all the setup to (at a high level) 3 commands:

```bash
$ amplify init
$ amplify add api
$ amplify push
```

[Amplify CLI](https://docs.amplify.aws/cli/graphql-transformer/codegen) also automatically generates queries, mutations, subscriptions, and types for the frontend app to consume!

You can always start with Amplify then move to CloudFormation or CDK:

```ts
export class AppsyncCdkAppStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Creates the AppSync API
    const api = new appsync.GraphqlApi(this, 'Api', {
      name: 'cdk-notes-appsync-api',
      schema: appsync.Schema.fromAsset('graphql/schema.graphql'),
    });

    // Prints out the AppSync GraphQL endpoint to the terminal
    new cdk.CfnOutput(this, "GraphQLAPIURL", {
     value: api.graphqlUrl
    });
  }
} 
```

### Realtime Subscriptions

AppSync lets you specify which part of your data should be available in a real-time manner using [GraphQL Subscriptions](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html).

```graphql
type Subscription {
    addedPost: Post
    @aws_subscribe(mutations: ["addPost"])
    updatedPost: Post
    @aws_subscribe(mutations: ["updatePost"])
    deletedPost: Post
    @aws_subscribe(mutations: ["deletePost"])
}
```

These then have to be scalable. [AppSync is load tested up to 10 million active websockets](https://aws.amazon.com/blogs/mobile/appsync-realtime/):

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wqyswzajywq4wndgbbmb.png)

### Search

[AppSync supports Amazon Elasticsearch](https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-elasticsearch-resolvers.html). The GraphQL operations support simple lookups, complex queries and mappings, full text searches, fuzzy/keyword searches, even [geo lookups](https://medium.com/@andrewgriffiths/build-a-geosearch-graphql-api-using-aws-appsync-elasticsearch-5d7f0f47f0b3).

### Proxying an Existing Backend

You can set up [AppSync with AWS Lambda Resolvers](https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html) so you don't have to do a total rewrite!

### Security: Authorization, Roles, Permissions

4 kinds of authz:

- [API_KEY](https://docs.aws.amazon.com/appsync/latest/devguide/security.html#api-key-authorization) for unauthenticated throttling of APIs, mostly used in development or for public APIs. Manually rotate API keys every 365 days.
- [AWS_IAM](https://docs.aws.amazon.com/appsync/latest/devguide/security.html#aws-iam-authorization)
- [OPENID_CONNECT](https://docs.aws.amazon.com/appsync/latest/devguide/security.html#openid-connect-authorization): enforces OpenID Connect (OIDC) tokens provided by an OIDC-compliant service. 
- [AMAZON_COGNITO_USER_POOLS](https://docs.aws.amazon.com/appsync/latest/devguide/security.html#amazon-cognito-user-pools-authorization): enforces OIDC tokens provided by Amazon Cognito User Pools.

This last one provides a lot of group based controls to make your application multi-tenant. You can finetune which fields and operations are available to various groups of users:

```graphql
type Query {
   posts:[Post!]!
   @aws_auth(cognito_groups: ["Bloggers", "Readers"])
}

type Mutation {
   addPost(id:ID!, title:String!):Post!
   @aws_auth(cognito_groups: ["Bloggers"])
}
```

For even more finegrained permissions you can use:

- [Resolver Mapping Templates](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-overview.html) (currently written in [VTL](https://velocity.apache.org/engine/1.7/user-guide.html) or [Direct Lambda Resolvers](https://aws.amazon.com/blogs/mobile/appsync-direct-lambda/), though other options are on their way.)
- Reusable checks (eg authorization checks) can be composed using [Pipeline resolvers](https://docs.aws.amazon.com/appsync/latest/devguide/pipeline-resolvers.html)

### Caching and Offline Data Sync

[I've written about this one before.](https://www.swyx.io/svelte-amplify-datastore/)

### Testing

Slobodan says this is a topic for a future talk... but `amplify mock` offers basic [local mocking](https://aws.amazon.com/blogs/mobile/amplify-framework-local-mocking/).

### Event Sourcing/CQRS

When you have to do `client -> mutation -> event storage -> eventbridge -> business logic -> subscription -> back to client`, with another process for OLAP workloads. AppSync can handle all this.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/e8t3cebuueo4bysspasz.png)

## His Summary

- GraphQL makes your frontend and backend connection effortless
- AppSync makes GraphQL management effortless
- Serverless GraphQL is a great option.

## Sketch Notes

I love some sketch notes! [The Serverless Days folks did some](https://twitter.com/ServerlessdaysV/status/1321520472987631616?s=20):

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/56f9qy0gfh8ua5fz55nh.jpeg)
