
Serverless Chat on AWS with AppSync Events
This article shows how to build a cloud-native, serverless chat on AWS using AppSync Events. It covers the architecture, implementation with CDK, and addresses some of the missing features and limitations AppSync Events currently has.
AWS AppSync Events lets you create secure and performant serverless WebSocket APIs that can broadcast real-time event data to millions of subscribers, without you having to manage connections or resource scaling.
onPublish
and onSubscribe
handlers, however since they run on AppSync's JavaScript runtime there is no possibility to do much more than on the fly processing or filtering of the payload.@aws-cdk/aws-pipes-alpha
, @aws-cdk/aws-pipes-sources-alpha
, @aws-cdk/aws-pipes-targets-alpha
and this is what it takes to connect with DynamoDB Streams:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// EventBridge Pipe DynamoDB Stream Source
const dynamoDbStreamSource = new DynamoDBSource(table, {
startingPosition: DynamoDBStartingPosition.LATEST,
});
// EventBridge API Destination
const appSyncEventsApiDestination = new ApiDestination(this, 'AppSyncEventsApiDestination', {
connection: appSyncEventsApiConnection,
endpoint: appSyncEventsApiEndpoint,
httpMethod: HttpMethod.POST,
});
// EventBridge Pipe with API Destination Target & Input Transformation
const pipe = new Pipe(this, 'EBPipe', {
source: dynamoDbStreamSource,
target: new ApiDestinationTarget(appSyncEventsApiDestination, {
inputTransformation: InputTransformation.fromObject({
channel: 'serverlesschat/channels/' + '<$.dynamodb.NewImage.channel.S>',
events: [
JSON.stringify({
channel: '<$.dynamodb.NewImage.channel.S>',
timestamp: '<$.dynamodb.NewImage.timestamp.S>',
username: '<$.dynamodb.NewImage.username.S>',
message: '<$.dynamodb.NewImage.message.S>',
})
],
}),
// api key must be sent with each message
headerParameters: {
'X-Api-Key': appSyncEventsApiKey,
}
}),
});
1
2
3
4
{
"channel": "string",
"events": ["..."]
}
events
is an array of strings, hence json messages are stringified during transformation.Pro tip: activating CloudWatch logs for the Pipe with Log execution data turned on can save you a bunch of time troubleshooting.
X-Api-Key
header sent with each request for the messages to get through. What I noticed is that once this header is missing, or the value is incorrect - the Connection becomes Deauthorized
automatically and the whole Pipe stops working as a result. I haven't found a way to fix that, but just to destroy and deploy the stack again. I am not sure what it takes to authorize the API Destination again, but it was rather inconvenient from developer experience standpoint.fetch
and websocket
APIs, without any external dependencies. You don't have to worry about the technicalities if you just want to run the example yourself, however if you'd like to dive deeper on how to connect to AppSync Events without Amplify, feel free to consult Understanding the Event API WebSocket protocol AWS guide and my code.