This chapter is included in the free preview

AWS AppSync

AWS AppSync is a managed GraphQL service in the AWS cloud. If you opt to use it, you don't need to think about servers, capacity management, or software updates. Just like with other managed services, you need to configure it correctly and operations is done by AWS. Also, it scales without thresholds, unlike services like OpenSearch or EC2, making it a serverless solution.

Apart from the operational benefits, it also provides a few extra features. It integrates with Cognito, which makes it easy to add user sign-in functionality to the API, and it also provides a few directives for schema-based access control. Also, it allows IAM entities (users, and roles) to securely call the API, which makes it possible to give access to processes, such as Lambda functions or EC2 instances.

type Query {
  # everybody can get themselves
  currentUser: User

  # only admins can query all users
  allUsers: [User]
  @aws_cognito_user_pools(cognito_groups: ["admin"])
}

On top of the GraphQL-defined scalars, AppSync adds a few extra and it also provides built-in validations for them. The AWSDate, the AWSTime, and the AWSDateTime are checked to be in ISO 8601 format (for example, 2022-02-08T10:01:31.474Z), the AWSJSON is a string that is a valid JSON, then the AWSEmail, the AWSPhone, the AWSURL, and the AWSIPAddress all provide some verification to make sure that the value conforms to the expected structure.

AppSync's implementation of resolvers is based on a simplified version of JavaScript that configures how AppSync integrates with a separate service. For example, it can define how to fetch an item from a DynamoDB table for a GraphQL query and how to transform the result back to the GraphQL world.

Resolvers integrate with other AWS services: DynamoDB, RDS, Lambda, OpenSearch, and it support a generic HTTP data source that you can use to integrate with others on the HTTP level.

// sends a GetItem to a DynamoDB table
return {
  version: "2018-05-29",
  operation: "GetItem",
  key: {
    id: {S: ctx.args.id}
  },
  consistentRead: true
}

One of the main selling point of AppSync is that it supports subscriptions. These are real-time data notifications that pushes data to interested clients, for example, the result of a live sport event can be immediately shown for all visitors. Under the hood, it uses a WebSocket connection, but unlike API Gateway WebSocket APIs, you don't need to handle anything about the individual clients, it is all managed by AppSync. All you need to do is define when it needs to send a notification and it will do the rest, no matter if it's sent to 1 or 1 million clients.

WebSocket-based subscription events

As usual, AppSync fits into the AWS ecosystem: it sends its logs to CloudWatch Logs, metrics to CloudWatch, gets its permissions via IAM Roles, can be deployed with CloudFormation or the CDK, and you can use the Web Application Firewall (WAF) to filter traffic.

AppSync API metrics
AppSync strengths
  • Fully managed service
  • Supports Cognito and IAM for authentication
  • Extra scalars
  • Direct integration with several data sources
  • Real-time data with subscriptions
  • Integrates with the AWS ecosystem

But AppSync has several drawbacks too. A fully managed service is a double-edged sword: if it supports everything you need then it frees you from managing the individual parts. But a missing or broken feature is a source of frustration. And usually the only course of action you can take is to voice your frustration on forums and hope AWS listens.

Just like all AWS services, there are hard limits that you can't change: the maximum schema size, the response size and timeout, as well as the maximum items per resolvers. These are high enough for most applications and if you follow best practices you are unlikely to hit them, but it's good to know that there are immutable values.

Not really a shortcoming of AppSync, but keep in mind that while it supports SQL data sources (RDS, in particular) that needs to use the Data API which is request-based instead of the connection-based native SQL connections. It's a usual serverless pitfall that you can't use the much more optimized direct SQL connections but have to send stateless requests. In practice, that brings database query times from single-digit to low triple-digits milliseconds.

AppSync weaknesses
  • Missing features
  • Resolver development problems
  • Hard limits