Front-End Web & Mobile

Announcing AWS AppSync Events: serverless WebSocket APIs to power real-time web and mobile experiences at any scale

Today, AWS AppSync announced AWS AppSync Events, a feature that lets developers easily broadcast real-time event data to a few or millions of subscribers using secure and performant serverless WebSocket APIs. With AWS AppSync Events, developers no longer have to worry about building WebSocket infrastructure, managing connection state, and implementing fan-out. Developers simply create their API, and publish events that are broadcast to clients subscribed over a WebSocket connection. AWS AppSync Event APIs are serverless, so you can get started quickly, your APIs automatically scale, and you only pay for what you use. In this blog, I’ll discuss AWS AppSync Events, describe what AWS AppSync Event APIs are, and show you how you can get started.

Real-time event updates are a significant component of apps today and provide a differentiated experience to users. From live sports scores, group chat messages, price levels, or location updates, developers want to build apps that give their customers pertinent up-to-the-second information. But this functionality is not easy to implement and is hard to scale. This changes with AWS AppSync Events. AWS AppSync Event APIs are easy to set up, so developers can get started quickly and can connect to their WebSocket endpoint using standard Web APIs. AWS AppSync Event APIs are serverless, and can scale to broadcast real-time updates to millions of connected clients. For organizations that have invested in event-driven architectures, AWS AppSync Events support publishing over an HTTP endpoint. This makes integration with popular services like Amazon EventBridge simple, and makes it easy to publish backend-generated events to web and mobile applications.

With AWS AppSync Events, you start by creating an API and defining its basic configuration, like which authorization modes are supported. You then create your channel namespace by assigning it a name, which is also the prefix of all channels within that namespace. A channel namespace defines the capabilities of its channels. For example, a channel namespace with the name “messages” allows you to publish and subscribe to channels that begin with /messages. Channels in a namespace are ephemeral and are created as needed. For example, you can publish events to /messages/group/admin or /messages/user/JohnDoe on demand. You can subscribe to events on a specific channel like /messages/user/JohnDoe, or a subset by using a wildcard at the end of a channel path like /messages/* or /messages/user/*.

Getting started in the console

You can get started by visiting the AWS AppSync console. From there, choose “Create API”, and select “Event API”. Give your API a name, and choose “Create”. In a few seconds, your API is created and ready to use. In the console, the service creates an Event API, a default namespace, and an API key for you. You can achieve the same result with the AWS CLI, AWS SDKs, AWS CloudFormation, or AWS CDK.

Next, head over to the Pub/Sub Editor. The editor provides an easy way to publish and subscribe directly from the console. It’s a great way to test out ideas quickly and verify functionality. You can use the editor to publish events over HTTP and set up subscriptions over a WebSocket connection. To receive events, in the Subscribe section, choose “Connect”, and then “Subscribe”. Your API is now ready to receive events published to the channel. The HTTP endpoint supports publishing batches of up to 5 events. To publish from the console, simply provide an array of JSON objects. For example, enter the values in the Publish section:

[
  { "message": "hello world!" },
  "New WebSocket API!",
  true,
  100,
  ["L", "G", "T", "M"]
]

You receive 5 events in the Subscribe section!

a table with a list of received events

Integrate with your application

Building an application that uses AWS AppSync Events is straightforward. You can use the Amplify client for AppSync Events, and find your API’s configuration information in the console’s Integrations tab.

Note that there are no external dependencies required to connect to your API in a web browser. The JavaScript code snippet below shows how you can connect to your endpoint using the browser’s Web API WebSocket. To use this code, from the your Event API Settings page, retrieve your HTTP and real-time DNS names, and copy your API key. Next, open your page’s developer console. Plug in your values in the snippet, paste the snippet in the developer console’s editor, and run the code.

const REALTIME_DOMAIN = ''
const HTTP_DOMAIN = ''
const API_KEY = ''

const authorization = { 'x-api-key': API_KEY, host: HTTP_DOMAIN }

function getAuthProtocol() {
  const header = btoa(JSON.stringify(authorization))
    .replace(/\+/g, '-') // Convert '+' to '-'
    .replace(/\//g, '_') // Convert '/' to '_'
    .replace(/=+$/, '') // Remove padding `=`
  return `header-${header}`
}

const socket = await new Promise((resolve, reject) => {
  const socket = new WebSocket(
    `wss://${REALTIME_DOMAIN}/event/realtime`,
    ['aws-appsync-event-ws', getAuthProtocol()])
  socket.onopen = () => {
    socket.send(JSON.stringify({ type: 'connection_init' }))
    resolve(socket)
  }
  socket.onclose = (evt) => reject(new Error(evt.reason))
  socket.onmessage = (event) => console.log('=>', JSON.parse(event.data))
})

socket.send(JSON.stringify({
  type: 'subscribe',
  id: crypto.randomUUID(),
  channel: '/default/*',
  authorization
}))

You can send events by using your browser’s Web API fetch method. For example, run the following in the developer console.

const event = {
  "channel": "/default/introductions",
  "events": [
    JSON.stringify({message:'Hello World! Introducing AWS AppSync Events!'})
  ]
}

const response = await fetch(`https://${HTTP_DOMAIN}/event`, {
  method: 'POST',
  headers: authorization,
  body: JSON.stringify(event)
})

console.log(response)

To learn more about connection, authorization, and using WebSockets, see our documentation.

Working with event handlers

With AWS AppSync Events, you can define business logic to run when published events are processed and when clients try to subscribe to a channel. This is done with event handlers, functions that are defined in your channel namespaces. Event handlers are optional, and scoped to a channel namespace. AWS AppSync Events supports 2 type of handlers: onPublish handlers, and onSubscribe handlers. An onPublish handler is called when events are received, and before they are broadcast to connected clients. From your onPublish handler, you can transform the shape of your event payloads, filter out events, and reject published events. Handlers run on the APPSYNC_JS runtime, so you just write JavaScript. For example, to transform events, simply call map on your events array, making sure to return the event id, and the event payload:

export function onPublish(ctx) {
  return ctx.events.map(event => ({
    id: event.id,
    payload: {
      ...event.payload,
      message: event.payload.message.toUpperCase()
    }
  }))
}

To filter out events, silently dropping them so they are not broadcasted to subscribed clients, filter out the list and return what you want broadcast. For example, you can just call filter on the events array. Imagine you only want to broadcast events for a game where the winning odds are greater than 90%:

export function onPublish(ctx) {
  return ctx.events.filter(event => event.payload.odds > 0.9)
}

Filtering allows you to silently drop events, but you can also return errors to the publishers as you drop the event. For example, to enforce that events should always include a greeting message and return an error to the publisher:

export function onPublish(ctx) {
  return ctx.events.map(event => {
    if (!event.payload.message) {
      return {
        ...event,
        error: 'You should always included a greeting.'
      }
    }
    return event
  })
}

The onSubscribe handler is called when a client attempts to establish a subscription. You can reject a subscription by calling util.unauthorized(). Imagine you want to restrict your Amazon Cognito User Pools authenticated users to their own channel:

export function onSubscribe(ctx) {
  if (ctx.info.channel.path !== `/messages/inbox/${ctx.identity.username}`) {
    console.error(`user ${ctx.identity.username} tried connecting to wrong channel: ${ctx.info.channel.path}`)
    util.unauthorized()
  }
}

Now clients can only subscribe to channels that match the pattern /messages/inbox/<username>.

Event-driven architecture (EDA)

AWS AppSync Events fits in seamlessly with EDA patterns. With Amazon EventBridge, you can configure an API destination to forward events to AWS AppSync Events HTTPS endpoint.

In the EventBridge console, create a new connection with “API Key” as the authorization type. For the API Key name, enter x-api-key, and for the Value, enter the value of your API key. Next, create a new API destination. For the API destination endpoint, use the format https://<HTTP_DOMAIN>/event , where <HTTP_DOMAIN> is your HTTP domain you copied earlier. Set the HTTP method to POST. For the Connection type , select the connection you just created, and create the destination. You can now create a rule that uses the destination as a target. For your target’s input path (InputPath), specify "$.detail"; this will forward the entire event details to your Event API.

You can now forward events to AWS AppSync Event. For example, publish to EventBridge using the following event detail.

{
  "channel": "/default/introductions",
  "events": [
    "{\"message\":\"Hello from EventBridge!\"}"
  ]
}

Exploring API capabilities

You can configure your API with multiple authorization modes, and configure different authorization behavior on each of your channel namespaces. You can associate a custom domain with your API and attach an AWS Web Application Firewall to further protect it. Integration with Amazon CloudWatch Metrics and Amazon CloudWatch Logs is also available, giving you full insight into the performance of your API.

What’s next

In this article, I introduced AWS AppSync Events and described how you can get started with an AWS AppSync Event API. I described channel namespaces, channels, handlers how to integrate with Amazon EventBridge.

Today’s launch is an important milestone for AWS AppSync Events, but we are just getting started. In the near future, we plan to add support for bi-directional WebSockets and data sources. This will allow you to create custom sources and destinations, and will allow you to enrich or persist your events using data sources like Amazon DynamoDB or Amazon Aurora. We plan to add AWS Lambda functions as alternatives to handlers. We also plan to support schema validation to easily share and enforce type shapes. Stay tuned!

Conclusion

AWS AppSync Events is now available in all regions where AWS AppSync is available. To create your first Event API, visit the AWS AppSync console. AWS AppSync Events is a serverless feature: you pay only for AWS AppSync Event API operations and real-time connection minutes. Get started with 250,000 real-time Event API operations per month for free. To learn more about AWS AppSync Events, visit our documentation. For more information on pricing, see our pricing page.


AWS AppSync makes it easy to connect applications to events, data, and AI models. With AWS AppSync Events, you can create real-time experiences by publishing updates from any event source to subscribed clients over serverless WebSockets. With AWS AppSync GraphQL, you can connect applications to multiple databases, microservices, and AI models via a single GraphQL API endpoint.