© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
BENGALURU
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
AppSync in the Real World
ADITHYA REDDY | SDE @ BRANCH FINANCIAL
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
What is AppSync
• “Build data-driven apps with real-time and offline capabilities”
• Fully managed, serverless GraphQL service
• Client SDKs + Offline programming model
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Clients
iOS
Android
JS
Managed
Datastores
RDS
DynamoDB
Neptune
Middle-Tier
K8s
Docker
VMs
Storage
Streams
Search
Logging
Auth
ETL
Analytics
Validation
Logic
You operate You don’t operate
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Clients
iOS
Android
JS
Managed
Datastores
RDS
DynamoDB
Neptune
Middle-Tier
K8s
Docker
VMs
S3
Kinesis
ES Service
CloudWatch
Cognito
EMR
Athena
Validation
Logic
You operate You don’t operate
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Hub for all your managed services
• Provide a single unified API layer over all your data sources.
• Fetch, shape, transform, and aggregate data into exactly
what the client asked for.
• Replace the middle layer of (most) apps.
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
• Validating requests and payloads
• Authentication
• Fine-grained permissions
• Access control
What AppSync can do
• Fetching/writing data to/from data sources
• Real-time updates
• Offline with optimistic UI updates
• Resolving data conflicts
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
GraphQL
101
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
A strongly typed, declarative
query language for APIs.
graphql.org
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Describe your data with a schema
type Tweet {
id: ID
body: String
date: Date
Author: User
}
type User {
id: ID
username: String
tweets: [Tweet]
}
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Queries and Mutations
type Query {
getTweet(id: ID): Tweet
allTweets: [Tweet]
}
type Mutation {
newTweet(body: String): Tweet
newUser(username: String): User
}
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Ask for exactly the data you need
query {
getUser(id: "123") {
username
tweets {
body
date
}
}
}
{
"username": "...",
"tweets": [
{
"body": "...",
"date": "..."
},
{
"body": "...",
"date": "..."
},
]
}
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Subscriptions
type Subscription {
userTweeted(id: ID): Tweet
@aws_subscribe(mutations: ["newTweet"])
}
Subscription {
userTweeted(id: "jdoe123") {
body
}
}
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
• DynamoDB
• Elasticsearch
• Lambda
• HTTP
• Everything else (via Lambda)
Data Sources
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Resolvers
• Translate GraphQL requests to / from formats your data sources understand.
• Request and response mapping templates.
• Apache VTL (Velocity Template Language).
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Request Mapping
Template
Response Mapping
Template
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
{
"version": "2017-02-28",
"operation": "PutItem",
"key": {
"requestId": { "S": $util.autoId() }
},
"attributeValues": {
"timestamp": { "S": $util.time.nowISO8601() },
"requesterName": { "S": $context.args.name },
"requesterPhone": { "S": $context.args.phone }
}
}
mutation {
requestCall(
name: String!,
phone: String!
): Boolean
}
DynamoDB PutItem
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
#set($moistures = [])
#foreach($reading in ${context.args.moisture})
$util.qr($moistures.add($util.dynamodb.toMapValues($reading)))
#end
#set($pHs = [])
#foreach($reading in ${context.args.pH})
$util.qr($pHs.add($util.dynamodb.toMapValues($reading)))
#end
{
"version": "2018-05-29",
"operation": "BatchPutItem",
"tables": {
"moistureReadings": $util.toJson($moistures),
"pHReadings": $util.toJson($pHs)
}
}
input Moisture {
timestamp: String
value: Float
}
input pH {
timestamp: String
value: Float
}
mutation {
record(
moisture: [Moisture],
pH: [pH]
)
}
DynamoDB Multi-Table Batch PutItem
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Field Resolvers
type Post {
id: ID!
text: String
comments: [Comment]
}
type Comment {
postId: ID!
commentId: String!
text: String
}
Posts
id text
Comments
postId commentId text
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Field Resolvers
type Post {
id: ID!
text: String
comments: [Comment]
}
type Comment {
postId: ID!
commentId: String!
text: String
}
{
"version": "2017-02-28",
"operation": "Query",
"query": {
"expression": "postId = :postId",
"expresssionValues": {
":postId": { "S": "$context.source.id" }
}
}
}
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
More things you can do
• Pagination & Scans (limit, nextToken)
• Multi-table Batch Get / Update / Delete
• Conditional Get / Put / Update / Delete (via Conditional Expressions)
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
• API Key
• AWS IAM (access key + secret key / Cognito Federated Identities)
• Cognito User Pools
Security
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
context.identity
{
"sub": "...uuid...",
"username": "...",
"claims": { ...x },
"cognitoIdentityId": "...",
"cognitoIdentityPoolId": "..."
}
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
type Mutation {
addPost(id: ID!, title: String!): Post!
@aws_auth(cognito_groups: [“Bloggers", "Admins"])
}
Using Cognito Groups
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
"condition": {
"expression": “contains(#author, :username)",
"expressionNames": {
"#author": "Author"
},
"expressionValues": {
“:username": { "S": "${context.identity.username}" }
}
}
Proceed only if author field matches username
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
• JavaScript (+ React, Angular, Vue.js)
• React Native
• iOS (Objective-C / Swift)
• Android (Java / Kotlin)
AppSync Client SDKs
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
.NET Clojure
GoElixir PHP Scala
RubyPython
Standards Compliant GraphQL Clients
Unity
Perl
Extras (offline support / optimistic updates) library dependent
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
AWS Amplify Apollo
• Auth
• Storage
• Analytics
• Notifications
• Declarative data fetching
• Normalized write-through cache
• Optimistic UI
• Deferred queries
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Online
UI Component
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Offline
UI Component
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Back Online
UI Component
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
React Example
GET_POSTS = gql`
{
posts {
title
publishDate
previewText
}
}
`;
<Query query={GET_POSTS}>
{({ loading, data }) => {
if (loading) return <LoadingSpinner />;
return <PostsList data={data.posts} />;
}}
</Query>
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Optimistic UI
UI Component
message {
timestamp: "2018-09-30T23:43:05+05:30"
text: "Hello",
sent: False
}
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Optimistic UI
UI Component
message {
timestamp: "2018-09-30T23:43:05+05:30"
text: "Hello",
sent: True
}
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Branch’s Architecture
Other
services
Customer
Apps
Staff
Staff
AppSync
Customer
AppSync
Customer Auth Staff Auth
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
What we love 😍
• Much much much less code!
• No VMs, no containers to orchestrate, no uptime / reliability issues.
• Tightly integrated dev/ops workflow.
• Focus on what sets your business apart, instead of re-inventing the wheel.
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
What isn’t so great 😕
• No first-class RDS support (have to go through Lambda).
• HTTP resolvers only work for public APIs — have to go through Lambda for endpoints
inside VPCs.
• Resolver mapping templates are hard to debug.
• Need a Lambda function to index DynamoDB into Elasticsearch (super common).
• Terraform support lagging behind.
• Subscription updates are only triggered by mutations — not by external sources.
© 2018, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Adithya Reddy
@TheTallpants
github.com/tallpants
TheTallpants@gmail.com

AppSync in real world - pitfalls, unexpected benefits & lessons learnt

  • 1.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. BENGALURU
  • 2.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. AppSync in the Real World ADITHYA REDDY | SDE @ BRANCH FINANCIAL
  • 3.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. What is AppSync • “Build data-driven apps with real-time and offline capabilities” • Fully managed, serverless GraphQL service • Client SDKs + Offline programming model
  • 4.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Clients iOS Android JS Managed Datastores RDS DynamoDB Neptune Middle-Tier K8s Docker VMs Storage Streams Search Logging Auth ETL Analytics Validation Logic You operate You don’t operate
  • 5.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Clients iOS Android JS Managed Datastores RDS DynamoDB Neptune Middle-Tier K8s Docker VMs S3 Kinesis ES Service CloudWatch Cognito EMR Athena Validation Logic You operate You don’t operate
  • 6.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Hub for all your managed services • Provide a single unified API layer over all your data sources. • Fetch, shape, transform, and aggregate data into exactly what the client asked for. • Replace the middle layer of (most) apps.
  • 7.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. • Validating requests and payloads • Authentication • Fine-grained permissions • Access control What AppSync can do • Fetching/writing data to/from data sources • Real-time updates • Offline with optimistic UI updates • Resolving data conflicts
  • 8.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. GraphQL 101
  • 9.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. A strongly typed, declarative query language for APIs. graphql.org
  • 10.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Describe your data with a schema type Tweet { id: ID body: String date: Date Author: User } type User { id: ID username: String tweets: [Tweet] }
  • 11.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Queries and Mutations type Query { getTweet(id: ID): Tweet allTweets: [Tweet] } type Mutation { newTweet(body: String): Tweet newUser(username: String): User }
  • 12.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Ask for exactly the data you need query { getUser(id: "123") { username tweets { body date } } } { "username": "...", "tweets": [ { "body": "...", "date": "..." }, { "body": "...", "date": "..." }, ] }
  • 13.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Subscriptions type Subscription { userTweeted(id: ID): Tweet @aws_subscribe(mutations: ["newTweet"]) } Subscription { userTweeted(id: "jdoe123") { body } }
  • 14.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved.
  • 15.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. • DynamoDB • Elasticsearch • Lambda • HTTP • Everything else (via Lambda) Data Sources
  • 16.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Resolvers • Translate GraphQL requests to / from formats your data sources understand. • Request and response mapping templates. • Apache VTL (Velocity Template Language).
  • 17.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Request Mapping Template Response Mapping Template
  • 18.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. { "version": "2017-02-28", "operation": "PutItem", "key": { "requestId": { "S": $util.autoId() } }, "attributeValues": { "timestamp": { "S": $util.time.nowISO8601() }, "requesterName": { "S": $context.args.name }, "requesterPhone": { "S": $context.args.phone } } } mutation { requestCall( name: String!, phone: String! ): Boolean } DynamoDB PutItem
  • 19.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. #set($moistures = []) #foreach($reading in ${context.args.moisture}) $util.qr($moistures.add($util.dynamodb.toMapValues($reading))) #end #set($pHs = []) #foreach($reading in ${context.args.pH}) $util.qr($pHs.add($util.dynamodb.toMapValues($reading))) #end { "version": "2018-05-29", "operation": "BatchPutItem", "tables": { "moistureReadings": $util.toJson($moistures), "pHReadings": $util.toJson($pHs) } } input Moisture { timestamp: String value: Float } input pH { timestamp: String value: Float } mutation { record( moisture: [Moisture], pH: [pH] ) } DynamoDB Multi-Table Batch PutItem
  • 20.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Field Resolvers type Post { id: ID! text: String comments: [Comment] } type Comment { postId: ID! commentId: String! text: String } Posts id text Comments postId commentId text
  • 21.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Field Resolvers type Post { id: ID! text: String comments: [Comment] } type Comment { postId: ID! commentId: String! text: String } { "version": "2017-02-28", "operation": "Query", "query": { "expression": "postId = :postId", "expresssionValues": { ":postId": { "S": "$context.source.id" } } } }
  • 22.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. More things you can do • Pagination & Scans (limit, nextToken) • Multi-table Batch Get / Update / Delete • Conditional Get / Put / Update / Delete (via Conditional Expressions)
  • 23.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. • API Key • AWS IAM (access key + secret key / Cognito Federated Identities) • Cognito User Pools Security
  • 24.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. context.identity { "sub": "...uuid...", "username": "...", "claims": { ...x }, "cognitoIdentityId": "...", "cognitoIdentityPoolId": "..." }
  • 25.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. type Mutation { addPost(id: ID!, title: String!): Post! @aws_auth(cognito_groups: [“Bloggers", "Admins"]) } Using Cognito Groups
  • 26.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. "condition": { "expression": “contains(#author, :username)", "expressionNames": { "#author": "Author" }, "expressionValues": { “:username": { "S": "${context.identity.username}" } } } Proceed only if author field matches username
  • 27.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. • JavaScript (+ React, Angular, Vue.js) • React Native • iOS (Objective-C / Swift) • Android (Java / Kotlin) AppSync Client SDKs
  • 28.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. .NET Clojure GoElixir PHP Scala RubyPython Standards Compliant GraphQL Clients Unity Perl Extras (offline support / optimistic updates) library dependent
  • 29.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. AWS Amplify Apollo • Auth • Storage • Analytics • Notifications • Declarative data fetching • Normalized write-through cache • Optimistic UI • Deferred queries
  • 30.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Online UI Component
  • 31.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Offline UI Component
  • 32.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Back Online UI Component
  • 33.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. React Example GET_POSTS = gql` { posts { title publishDate previewText } } `; <Query query={GET_POSTS}> {({ loading, data }) => { if (loading) return <LoadingSpinner />; return <PostsList data={data.posts} />; }} </Query>
  • 34.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Optimistic UI UI Component message { timestamp: "2018-09-30T23:43:05+05:30" text: "Hello", sent: False }
  • 35.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Optimistic UI UI Component message { timestamp: "2018-09-30T23:43:05+05:30" text: "Hello", sent: True }
  • 36.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Branch’s Architecture Other services Customer Apps Staff Staff AppSync Customer AppSync Customer Auth Staff Auth
  • 37.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. What we love 😍 • Much much much less code! • No VMs, no containers to orchestrate, no uptime / reliability issues. • Tightly integrated dev/ops workflow. • Focus on what sets your business apart, instead of re-inventing the wheel.
  • 38.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. What isn’t so great 😕 • No first-class RDS support (have to go through Lambda). • HTTP resolvers only work for public APIs — have to go through Lambda for endpoints inside VPCs. • Resolver mapping templates are hard to debug. • Need a Lambda function to index DynamoDB into Elasticsearch (super common). • Terraform support lagging behind. • Subscription updates are only triggered by mutations — not by external sources.
  • 39.
    © 2018, AmazonWeb Services, Inc. or its Affiliates. All rights reserved. Adithya Reddy @TheTallpants github.com/tallpants TheTallpants@gmail.com