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
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
});
}
}
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"])
}
These then have to be scalable. AppSync is load tested up to 10 million active websockets:
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"])
}
For even more finegrained permissions you can use:
- Resolver Mapping Templates (currently written in VTL or Direct Lambda Resolvers, though other options are on their way.)
- Reusable checks (eg authorization checks) can be composed using Pipeline resolvers
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.
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: