03/05/24

Event-Driven Architecture

Concepts, use cases, and tools

5 Min Read

Event-Driven Architecture (EDA) has become increasingly popular, especially in systems utilizing microservices. Fundamentally it means you are using events to trigger and communicate between decoupled components within an application, as opposed to communicating directly via APIs in a Request/Reponse driven manner.

An event can be anything from a user action, like adding an item to a shopping cart, to a system update, such as an order being shipped. These events can carry detailed information or simply act as notifications of a particular state change.

Core Components of Event-Driven Architecture

Event-Driven Architectures typically consists of three main components:

  • Event Producers: These are the sources of events, generating notifications of state changes or updates.
  • Event Routers: Also known as event brokers or buses, these components filter and direct events from producers to the appropriate consumers.
  • Event Consumers: Services or components that react to the events, processing them as needed.

This architecture allows for services to be highly decoupled, meaning they operate independently of each other, which brings several benefits to the development process and system operation.

The benefits of Event-Driven Architectures

  • Scalability and Independent Failure: In an EDA, services are only aware of the event router and not each other. This decoupling allows services to scale and fail independently. If one component experiences a failure, it doesn't directly impact the others, enhancing the system's overall resilience.

  • Development Agility: Developers can focus on their specific services without worrying about the intricate details of communication between different parts of the system. The event router handles the distribution of events, which streamlines the development process and accelerates time to market.

  • Simplified Auditing and Policy Enforcement: Having a centralized event router simplifies the auditing of system activities and the enforcement of security and access policies. It becomes easier to control who can publish or subscribe to certain events and secure sensitive data in transit and at rest.

  • Cost Efficiency: EDA is inherently efficient, operating on a push-based mechanism where actions are taken on-demand in response to events. This reduces the need for continuous polling, saving on resources like network bandwidth and CPU usage.

When to Use Event-Driven Architecture

  • Parallel Processing: Enables a single event to trigger multiple processes simultaneously, without custom code for each consumer.
  • Cross-org and Cross-region Coordination: Ideal for systems that operate across different organizational units or geographical locations.
  • Integrating Diverse Systems: Facilitates communication between systems with different underlying technologies without tight coupling.
  • Building Systems that require Audit Logging: EDAs can simplify building audit logs as system communication can be logged as part of the messaging infrastructure.

Hang on, what about drawbacks?

Event-Driven Architectures introduce new requirements for maintaining a productive developer workflow:

  • Debugging can be complex and requires using observability tools like distributed tracing.
  • Architecture ends up reflecting org complexity, increasing importance of documentation and cataloging of services.
  • Requires experience in managing cloud services like Pub/Sub to ensure stability and avoid failures.

Pub/Sub as a foundation for an Event-Driven Architecture

Pub/Sub systems are a natural fit for implementing an EDA. They provide the necessary infrastructure for event producers to publish messages that are then consumed by interested subscribers. This model supports the dynamic and decoupled nature of EDA, allowing for flexible, scalable, and resilient system designs. Learn more about Pub/Sub.

Encore as a solution for efficient Event-Driven Application development

Encore provides a fully type-safe implementation of Pub/Sub via an Open Source Backend SDK, available for Go and TypeScript. It lets you define the common distributed systems resources like services, databases, cron jobs, and Pub/Sub, as type-safe objects in your application code.

With the SDK you only define infrastructure semanticsthe things that matter to your application's behavior — not configuration for specific cloud services. Encore parses your application and builds a graph of both its logical architecture and its infrastructure requirements, it then automatically generates boilerplate and orchestrates the relevant infrastructure for each environment. This means your application code can be used to run locally, test in preview environments, and provision and deploy to cloud environments on AWS and GCP.

This approach completely removes the need for mocks and emulators, and allows you to work offline and run you application locally. You also get the added benefit of avoiding having a separate infrastructure configuration like Terraform, since the application code becomes the source of truth for your application's infrastructure requirements.

When your application is deployed to your cloud, there are no runtime dependencies on Encore and there is no proprietary code running in your cloud.

Example: Creating a Pub/Sub topic

If you want a Pub/Sub Topic, you declare it directly in your application code, like so:

import "encore.dev/pubsub" type User struct { /* fields... */ } var Signup = pubsub.NewTopic[*User]("signup", pubsub.TopicConfig{ DeliveryGuarantee: pubsub.AtLeastOnce, }) // Publish messages by calling a method Signup.Publish(ctx, &User{...})

To run your application, you simply use encore run. Encore will automatically set up the local infrastructure and generate the boilerplate code necessary. You also get a local development dashboard with distributed tracing to help you understand and debug application behavior with ease.

Your code doesn't change when you want to deploy to the cloud. Encore will generate the necessary boilerplate and provision the necessary infrastructure in all environments:

  • NSQ for local development
  • GCP Pub/Sub for environments on GCP
  • SNS/SQS for environments on AWS

Conclusion

Event-Driven Architecture offers a flexible and scalable way to design and operate complex systems, especially those based on microservices. By leveraging Pub/Sub mechanisms, you can create decoupled systems that are resilient to failures, easy to scale, and quick to develop. Success with EDA requires a thoughtful approach and the appropriate tooling for local development, observability, and documentation.

Ready to escape the hamster wheel?

Encore is Backend Development Platform purpose-built for creating event-driven and distributed systems — from developing locally to scaling in your cloud on AWS/GCP.