Notes on Serverless GraphQL with AWS AppSync

swyx - Oct 28 '20 - - Dev Community

Slobodan Stojanovic 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):

Here are his slides

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 on the AWS Web Console... but you should use Amplify, CloudFormation or CDK for IaC.

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

$ amplify init
$ amplify add api
$ amplify push
Enter fullscreen mode Exit fullscreen mode

Amplify CLI 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:

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
    });
  }
} 
Enter fullscreen mode Exit fullscreen mode

Realtime Subscriptions

AppSync lets you specify which part of your data should be available in a real-time manner using GraphQL Subscriptions.

type Subscription {
    addedPost: Post
    @aws_subscribe(mutations: ["addPost"])
    updatedPost: Post
    @aws_subscribe(mutations: ["updatePost"])
    deletedPost: Post
    @aws_subscribe(mutations: ["deletePost"])
}
Enter fullscreen mode Exit fullscreen mode

These then have to be scalable. AppSync is load tested up to 10 million active websockets:

Alt Text

Search

AppSync supports Amazon Elasticsearch. The GraphQL operations support simple lookups, complex queries and mappings, full text searches, fuzzy/keyword searches, even geo lookups.

Proxying an Existing Backend

You can set up AppSync with AWS Lambda Resolvers so you don't have to do a total rewrite!

Security: Authorization, Roles, Permissions

4 kinds of authz:

  • API_KEY for unauthenticated throttling of APIs, mostly used in development or for public APIs. Manually rotate API keys every 365 days.
  • AWS_IAM
  • OPENID_CONNECT: enforces OpenID Connect (OIDC) tokens provided by an OIDC-compliant service.
  • AMAZON_COGNITO_USER_POOLS: 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:

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

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

For even more finegrained permissions you can use:

Caching and Offline Data Sync

I've written about this one before.

Testing

Slobodan says this is a topic for a future talk... but amplify mock offers basic 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

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:

Alt Text

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .