What is event-driven architecture (EDA)?
Event-driven architecture (EDA) is a modern architecture pattern built from small, decoupled services that publish, consume, or route events.
An event represents a change in state, or an update. For example: an item placed in a shopping cart, a file uploaded to a storage system, or an order becoming ready to ship. Events can either carry the state (such as the item name, price, or quantity in an order) or simply contain identifiers (for example, “order #8942 was shipped”) needed to look up related information.
Unlike traditional request-driven models, EDA promotes loose coupling between producer and consumer services. This makes it easier to scale, update, and independently deploy separate components of a system.
Why is a decoupled architecture important?
Many organizations find that monolithic applications, databases, and technologies negatively impact innovation and improvement of the user experience. Legacy applications and databases reduce your options for adopting modern technology frameworks and constrain your competitiveness and innovation. However, when you modernize applications and their data stores, they become easier to scale and faster to develop.
A decoupled data strategy improves fault tolerance and resiliency, which helps accelerate the time to market (TTM) for your new application features.
For more information about the advantages of modernizing monolithic applications, see Enabling data persistence in microservices in AWS Prescriptive Guidance.
What are the benefits of event-driven architecture (EDA)?
Event-driven architecture (EDA) promotes loose coupling between components of a system, leading to greater agility. Microservices can scale independently, fail without impacting other services, and reduce the complexity of workflows. Events can be flexibly routed, buffered, and logged for auditing purposes. Push-based flows of events can operate in real time, cutting costs associated with creating and operating code that continuously polls systems for changes.
Scale and fail independently
By decoupling services, components in an event-driven architecture can scale and fail independently, increasing the resiliency of an application. This becomes increasingly important as the number of integrations between services grows. If one service has a failure, the rest can keep running.
Event-driven architecture can also make it easier to design near real-time systems, helping organizations move away from batch-based processing. Events are generated when an application state changes. As events scale up, so can the layer that processes the events.
Events are typically published to messaging services that behave like an elastic buffer between microservices and help handle scaling. Events might also be sent to a router service that can filter and route messages based on the content of the event. As a result, event-based applications can be more scalable and offer greater redundancy than monolithic applications.
Develop with agility
With event-driven architecture and event routers, developers no longer need to write custom code to poll, filter, and route events. An event router automatically filters and pushes events to consumers. The router also removes the need for heavy coordination between producer and consumer services, which increases developer agility.
Event-driven architecture is push-based, meaning that everything happens on demand as events are sent to the router and downstream systems, without needing to inform dependent services. Because of this, infrastructure and resources can scale up and down with event volume, which reduces costs to process workloads and operate deployed applications.
Build extensible systems
Event-driven architecture is also highly extensible. Other teams can extend features and add functionality without impacting the existing microservices. By publishing events, an application can integrate with existing systems—and future applications can integrate easily as event consumers—without changing the existing solution.
Event producers have no knowledge of event consumers, so extending the system has less friction, and new features or integrations do not add dependencies that slow down future development.
Microservices enable developers and architects to decompose complex workflows. For example, they can break down an ecommerce monolith into order acceptance and payment processes with separate inventory, fulfillment, and accounting services.
A workload that might be complex to manage and orchestrate in a monolith becomes a series of simple, decoupled services that are managed independently and communicate asynchronously through event messages.
An event-driven approach makes it possible to assemble and orchestrate services that process data at different rates. In the following example, an order acceptance microservice interacts with a payment processing system via a queue.
In the example, the order acceptance service can store high volumes of incoming orders by buffering the messages in a queue.
The payment processing service, which is typically slower due to the complexity of handling payments, can take a steady stream of messages from the queue. The payment service transitions between various system states due to retry and error handling logic. The workflow service orchestrates and manages payment steps based on the system state, and eventually produces more events of interest to the Inventory, Fulfillment, and Accounting services.
Audit with ease
An event router in an event-driven architecture acts as a centralized location to audit your application and define policies. These policies can restrict who can publish and subscribe to a router and control which users and resources have permission to access your data. You can also encrypt your events both in transit and at rest.
EDAs are push-based, so everything happens on demand as the event presents itself in the router. This way, you’re not paying for continuous polling to check for an event. This means less network bandwidth consumption, less CPU utilization, less idle fleet capacity, and fewer SSL/TLS handshakes.
How does an event-driven architecture (EDA) work?
Below is example of an event-driven architecture (EDA) for an ecommerce site:
This example site shows three primary Event Producers components and the events that they produce. In this scenario, an Event Router ingests and filters the events, then it sends one or more events to the Event Consumers.
The event-driven architecture enables the site to react to changes from a variety of sources during times of peak demand, without crashing the application or over-provisioning resources.
What types of workloads are suited to event-driven architecture (EDA)?
Event-driven architectures (EDAs) can provide an effective way to meet the demands of highly scalable and highly available workloads. EDA also applies well to workloads with unpredictable or “spikey” traffic patterns.
How does event-driven architecture (EDA) improve applications?
Event-driven architecture (EDA) promotes loose coupling between components, which makes it a good approach to build modern, distributed applications.
Event producers are unaware of, unconcerned by, and unburdened by any activity of downstream consumers of the events that they produce. The events themselves represent a change in state and may or may not contain data. Events are unaware of consequences of their existence. Consumers listen and process events of interest. You can bring new consumers online to provide new functionality without disrupting existing workflows.
EDAs promote decomposition of monolithic systems into smaller domain models. Developers can get up to speed with less cognitive load and become productive quicker. When critical functions are decoupled, there is also less risk to deploy updates and new features.
What are some common event-driven architecture (EDA) use cases?
Microservices communication for web and mobile backends
Retail or media and entertainment websites often must scale up to handle unpredictable traffic. Customers visit an ecommerce website and place an order. The order event is sent to an event router. All of the downstream microservices can pick up the order event for processing. Example actions may include: submitting the order, authorizing payment, and sending the order details to a shipping provider.
Because each of the microservices can scale and fail independently, the process can scale up during peak order periods without single points of failure.
Business workflow automation
Many business workflows, such as financial services transactions, require repeating the same steps. You can initiate and automated those steps with event-driven architecture (EDA).
For example, when a customer applies for a new account with a bank, the bank must run a few data checks (identity documentation, address, etc.). Some accounts will also require a human approval stage. You can orchestrate all of these steps through a workflow service that runs steps automatically when new account applications are received.
You could also add a workflow to process customer application data asynchronously with machine learning to extract relevant data, potentially saving hours of manual data collection and validation.
SaaS application integration
A top challenge for software as a service (SaaS) environments is lack of visibility into user activity and data. To unlock siloed data, event-driven architectures can ingest SaaS application events or send events to their SaaS applications. For example, you can build middleware to ingest incoming partner order data and send the orders directly to an in-house order processing application.
When running compute intensive workloads (such as financial analyses, genomic research, or media transcoding), you can have compute resources respond by scaling up for highly parallel processing and then scaling down after the job is complete.
For example, in highly regulated industries, companies with an EDA can spin up security posture resources in response to an incident, or take remediation action whenever a security policy sends an alert event.
When should you use event-driven architectures (EDAs)?
Event-driven architectures (EDAs) are ideal for improving agility and moving quickly. They’re commonly found in modern applications that use microservices, or any application that has decoupled components.
Integration of heterogeneous systems
If you have systems running on different stacks, you can use an EDA to share information between them without coupling. The event router establishes indirection and interoperability among the systems, so they can exchange messages and data while remaining agnostic.
Cross-Region, cross-account data replication
You can use an EDA to coordinate systems between teams operating in and deploying across different AWS Regions and accounts. By using an event router to transfer data between systems, you can develop, scale, and deploy services independently from other teams.
Resource state monitoring and alerting
Rather than continuously checking on your resources, you can use an EDA to monitor and receive alerts on any anomalies, changes, and updates. These resources can include storage buckets, database tables, serverless functions, compute nodes, and more.
Fanout and parallel processing
If you have many systems that must operate in response to an event, you can use an EDA to fan out the event without having to write custom code to push to each consumer. The router pushes the event to the systems, each of which can process the event in parallel with a different purpose.
What are common event-driven architecture (EDA) patterns?
Many short functions
Create many short functions over fewer larger ones. Making functions highly specialized for your workload means that they are concise and generally reduce processing time. Each function should handle the event passed into the function, with no knowledge or expectations of the overall workflow or volume of transactions. This makes the function agnostic to the source of the event with minimal coupling to other services.
On-demand processing instead of batches
Many traditional systems are designed to run periodically and process batches of transactions that build up over time. For example, a banking application might run hourly to process ATM transactions into central ledgers.
In event-driven architecture (EDA), custom processing can respond to every event. This allows the service to scale up concurrency as needed to process transactions in near real time.
In the case of a disruption, a service might be automatically invoked to retry processing an event. Because the service might receive the same event more than once, design functions to be idempotent. This ensures that the result does not change after the first time the service receives the event.
For example, if a retailer tries to process a credit card twice due to a retry, the service processes the payment only on the first attempt. On the retry, the service verifies the payment status and discards the event.
What are some challenges with event-driven architecture (EDA)?
When adopting an event-driven architecture (EDA), you may need to rethink how you view your application design.
Unlike monolithic applications, which may process everything within the same memory space on a single device, event-driven applications communicate across networks. This design introduces variable latency. Although monolithic applications may have lower or less variable latency, this generally comes at the expense of scalability and availability.
The serverless AWS services are highly available, meaning that they operate in more than one Availability Zone in an AWS Region. In the event of a service disruption, services automatically fail over to alternative Availability Zones and retry transactions. As a result, instead of transactions failing, they may complete successfully but with higher latency.
Workloads that require consistent low-latency performance are not good candidates for EDA. Two examples are high-frequency trading applications in banks or sub-millisecond robotics automation in warehouses.
An event represents a change in state. With many events flowing through different services in an architecture at any given point of time, such workloads are often eventually consistent. This makes it more complex to process transactions, handle duplicates, or determine the exact overall state of a system.
Some workloads are not well suited for EDA due to the need for ACID properties. However, many workloads contain a combination of requirements that are eventually consistent (for example, total orders in the current hour) or strongly consistent (for example, current inventory). For those features needing strong data consistency, there are architecture patterns to support this. For example:
- DynamoDB can provide strongly consistent reads, sometimes at a higher latency, and it can also support transactions to help maintain data consistency.
- You can use relational databases for features needing ACID properties, though any relational database is less scalable than a NoSQL data store.
Returning values to callers
In many cases, event-based applications are asynchronous. This means that caller services do not wait for requests from other services before continuing with other work. This fundamental characteristic of EDAs enables scalability and flexibility; however, it makes passing return values or workflow results more complex than in synchronous flows.
In many cases, returning a value is less important than ensuring the success or failure of processing the event. Features that ensure processing of events may be more important than returning values to a caller.
For interactive workloads, such as web and mobile applications, the end user usually expects to receive a return value or the current status of a transaction. For these workloads, there are several design patterns that can provide rich eventing back to the caller. However, these implementations in an event-driven architecture are more complex than using a traditional asynchronous return value. The platform can often mitigate this complexity.
Debugging across services and functions
Debugging event-driven systems is different than debugging a monolithic application. As with all microservice-based applications and different systems and services passing events, it can be a challenge to record and reproduce the exact state of multiple services when an error occurs. Because each service and function invocation has separate log files, it can be more complicated to determine what happened to a specific event that caused an error.
It’s common for simple workflows to become more complex over time. In a typical monolith, this can result in more tightly coupled groups of functions and services, and complex code handling routing and exceptions.
To keep track of the state of the system, workflows that involve branching logic, different types of failure models, and retry logic typically use an orchestrator. When creating an event-driven serverless application, it’s important to identify when this is happening so that you can migrate this logic to a state machine for proper orchestration.
Which AWS services use an event-driven architecture (EDA)?
AWS services commonly produce or consume events, making it easy to build solutions with an event-driven architecture (EDA).
In addition, services such as Amazon EventBridge, Amazon SNS, Amazon SQS, and AWS Step Functions include features that help customers write less boilerplate code and build EDAs faster.
You can use Amazon EventBridge to build event buses for event-driven applications at scale using events from SaaS applications, other AWS services, or custom applications.
EventBridge applies rules to route events from event sources to different targets. Targets can include AWS services such as AWS Lambda, Step Functions, and Amazon Kinesis, or any HTTP endpoint through EventBridge API destinations.
A popular integration for EDA use cases is Step Functions, in which events trigger specific workflows.
AWS Step Functions
AWS Step Functions includes Workflow Studio, a low-code visual workflow designer that builders use to orchestrate different AWS services. You can use Workflow Studio to build distributed applications, automate IT and business processes, and build data and machine learning pipelines using AWS services.
We recommend using Amazon Simple Notification Service (Amazon SNS) to build applications that react to high throughput and low latency events published by other applications, microservices, or AWS services. You can also use Amazon SNS for applications that need very high fanout to thousands or even millions of endpoints.
Amazon Simple Queue Service (Amazon SQS) offers a secure, durable, and available hosted queue service that you can use to integrate and decouple distributed software systems and components. Amazon SQS offers common constructs such as dead-letter queues and cost allocation tags.
AWS Event-driven Architecture next steps
Instantly get access to the AWS free tier.
Get started building in the AWS Management Console.