Realtime Event-Driven Applications with AppSync Events and EventBridge Pipes



This content originally appeared on DEV Community and was authored by Ian

I want to share with you a powerful AWS serverless pattern that uses two of my favourite AWS services: AppSync Events and EventBridge Pipes. Using these services we can combine the power of event-driven architecture with realtime user notifications.

This article walks through how to build a demo application called Airspace Alerter, designed to showcase how these two services work together to deliver realtime user updates in a fully event-driven workflow.

Airspace Alerter

Airspace Alerter is a map based web application, but this isn’t a blog about geospatial data handling (although I’m passionate about that topic too!). This blog focuses on event management. If you’re interested in geospatial data in DynamoDB, check out my related post: Effective Handling of Geospatial Data in DynamoDB

Introduction

The full source code for this article can be found here:

👉 GitHub Repository – Airspace Alerter – CDK AppSync Events

In the demo, users can:

  • Submit and store their planned flight routes.
  • Simulate random airspace hazards (thunderstorms, drone sightings, restrictions).
  • See realtime alerts whenever a hazard impacts one of their routes.

These alerts are streamed back to the user through an open WebSocket connection using AppSync Events.

The Core Services

At the heart of this architecture are these two core AWS services:

1. EventBridge Pipes for Event Filtering and Enrichment

EventBridge Pipes act as a simple, fully-managed bridge between sources and targets, allowing filtering, transformation, and enrichment of events as they flow through. They are an alternative and more observable way to process events in your application, rather than using an EventBridge Bus with rules.

You can have multiple different sources for the pipes, but one of the most powerful is a DynamoDB stream. Streams is one the greatest features of DynamoDB, allowing for full Change Data Capture (CDC). This can be configured for all new, modified or deleted items to be passed to the pipes. The pipes allow a ‘fan out’ pattern where you can have multiple pipes, each with a specific filter. You only ever pay for a pipe when the filter matches and the pipe is invoked.

2. AppSync Events for Realtime Event Delivery

AppSync Events are AWS capability that provide realtime WebSocket event delivery. This is not AppSync as you might know it. They come under the same service name, but AppSync GraphQL API (a great GraphQL API service) is completely separate from AppSync Events API (a great JSON based event driven websocket).

AWS has two WebSocket services. API Gateway WebSocket API and AppSync Events. Think about AppSync events as API Gateway WebSocket APIs v2. WebSockets might not always be right for your application (see this great article by Allen Helton), but if they are, I would encourage you to use AppSync Events.

As a side note, I’m not quite sure why AWS chose to put AppSync Events under the AppSync service. It doesn’t naturally fit. I understand the need to consolidate services, but I tend to think of AppSync as purely AWS’s GraphQL offering.

Architecture Overview

The architecture looks like this:

Airspace Alerter Architecture

  1. User submits a flight route via the web application.
  2. The route is stored in DynamoDB.
  3. The user can trigger random hazard events (e.g., a thunderstorm, drone sighting) through API Gateway.
  4. A DynamoDB Stream captures the new hazard record and sends it through an EventBridge Pipe.
  5. The Pipe filters and then enriches the event: Fetching planned routes and checking if the hazard intersects with planned routes. If it does, it create an alert event.
  6. Both alert events and hazard events are passed to the target of the EventBridge pipe. The target is an EventBridge API Destination which is configured to POST to the AppSync Events endpoint.
  7. The connected user receives the hazards & alert in real time and sees it displayed on the map.

EventBridge Pipes handle filtering and enrichment. In our case, whenever a new hazard is inserted into the table, the event is picked up by the Pipe. Before the event is sent downstream, the Pipe performs an enrichment step, fetching flight routes from DynamoDB and determining whether any of them intersect with the hazard area.

If a hazard impacts a route, the event is marked as an alert. Both hazards and alerts are passed on to the target the pipe.

AppSync Events handle delivery to the web application. Clients simply subscribe once and wait for updates. AppSync Events handles some of the hidden complexity such as authentication, but more complex workflows requiring retries, specific authorisation will require additional logic that you build. Having said that, for a simple setup, it very easy to get working and the AWS Console provides some great tools to test and debug. Kudos to the AWS team here.

Building It with CDK

The demo is built entirely with the AWS CDK, which makes defining and connecting these event-driven components simple.

The key constructs include:

  • Pipe – EventBridge Pipe that defines the source (DynamoDB stream), enrichment (Lambda), and target (An API Destinations that publishes to AppSync Events). This is defined with an Alpha higher level construct @aws-cdk/aws-pipes-alpha. Alpha constructs are subject to breaking changes, so please be aware of this as you build. If you need stability, you can instead use the lower level cfnPipe construct.
  • EventApi – defines the AppSync Events WebSocket API and connection management. This is a really great, simple construct for deploying an AppSync Event API.
  • DynamoDB – Using a simple single-table design pattern for both the flight routes and the hazards. We can filter the stream in the EventBridge pipe if we are only interested in only one type of item.
  • Lambda – to handle route submission, hazard simulation, and enrichment logic.

Here’s an example of the enrichment pipe in CDK:

new Pipe(this, 'HazardEventsPipe', {
  source: new DynamoDBSource(props.airspaceAlerterTable, {
    startingPosition: DynamoDBStartingPosition.LATEST,
    batchSize: 1,
  }),
  target: new ApiDestinationTarget(airspaceAlertsAppsyncDestination),
  enrichment: new LambdaEnrichment(props.hazardsEnrichmentFunction),
  logLevel: LogLevel.TRACE,
  logIncludeExecutionData: [IncludeExecutionData.ALL],
  logDestinations: [cwlLogDestination],
  filter: sourceFilter,
});

This simple construct connects the DynamoDB stream, invokes the enrichment function, and publishes to the AppSync Events endpoint using a configured ‘API Destination’. This is how the pipe looks once it is deployed:

EventBridge Pipe

For testing, you can log all the pipe actions and the execution data which allows for good observability of the pipe invocations.

The AppSync Events API is deployed with just a few lines:

const apiKeyProvider = { authorizationType: AppSyncAuthorizationType.API_KEY };
const eventsApi = new EventApi(this, 'AirspaceAlerterEventsApi', {
  apiName: 'AirspaceAlertsEvents',
  authorizationConfig: { authProviders: [apiKeyProvider] },
});

// add a channel namespace called `alerts`
eventsApi.addChannelNamespace('alerts');

This gets you up and running with an API key for authentication. This is great for a demo, but in the real world, it also supports IAM, Cognito, OpenID Connect and custom authentication with Lambda.

Publishing Events

In this demo application, we are using the HTTP endpoint to publish events, and this has been integrated into the application using API Destinations, a feature of EventBridge.

In Airspace Alerter, the Pipe target is the API Destinations, with an array of events output from the enrichment phase posted to the endpoint.

However, you could also use a Lambda function as the destination from the pipe, for example, using IAM permissions to invoke the AppSync API rather than managing secrets.

In the current way to create an API Destination with CDK, you must provide a secret from AWS Secrets Manager which contains the API key. API Destinations then creates an additional secret it uses to store a copy of this key and the other header information. If like me, this annoys you ($0.40 a month for each secret), the Lambda destination pattern avoids this for some minor overhead in additional code maintenance.

Getting Started

To get started with the example project, clone the repo and deploy following the steps in the README.

Costs and Considerations

Each component scales independently and costs only when used:

  • DynamoDB Streams are low-cost and event-based.
  • EventBridge Pipes are charged per event processed.
  • AppSync Events have lightweight connection-based pricing.
  • Lambda only runs when invoked for enrichment or simulation.

The only caveat is the current AppSync Event destination pattern — as noted earlier, it relies on a Secret to store the API key connection.

Next Steps

Future enhancements might include:

  • Alternative, more secure authentication mechanisms (e.g. IAM, OIDC)
  • Multi-user subscription models with fine-grained filters
  • Use of IoT Core as a managed MQTT message broker instead of AppSync Events.

About Me

I’m Ian, an AWS Serverless Specialist, AWS Community Builder, and AWS Certified Cloud Architect based in the UK.

I work as an independent consultant with a passion for aviation, helping teams build cloud-native and event-driven solutions.

Connect with me on LinkedIn or find out more at Crockwell Solutions.


This content originally appeared on DEV Community and was authored by Ian