Eventuate explained using microservices patterns

A while back I came up with this diagram that explains Eventuate using microservice architecture patterns.

Let’s look at each of the patterns in turn starting with the Database per Service pattern.

Database per Service pattern

A key characteristic of the Microservice Architecture is loose coupling. There are two types of coupling:

  • design-time coupling - changing one service requires other services to change. Services must be loosely coupled from a design-time perspective in order to ensure that teams are loosely coupled and, therefore, productive.
  • runtime coupling - the failure of one service prevents another service from handling a request. Services must also be loosely coupled from a runtime perspective in order to maximize availability.

This requirement for loose coupling significantly impacts the database architecture and creates the need for the Database per Service pattern. At a minimum, to avoid design time coupling, services must not share database tables. And, ideally, to reduce runtime coupling, each service should have its own database server.

Distributed data management patterns

The Database per Service pattern creates distributed data management challenges. There are two key distributed data management patterns that solve these problems:

  • Saga pattern - implements transactions that span services
  • CQRS pattern - implements queries that span services

Transaction management with the Saga pattern

Some update operations (a.k.a. commands) need to update data in multiple services. Such an operation typically doesn’t use traditional distributed transactions (2PC) since that’s a type of runtime coupling. Instead, a command that spans services must be implemented using the Saga pattern. A saga is a series of local transactions that are coordinated by the participating services exchanging messages.

As I describe in this series of blog posts about sagas there are two types of saga coordination mechanisms:

  • choreography-based sagas - services collaborate by exchanging domain events
  • orchestration-based sagas - a centralized coordinator sending command messages to participants, which respond with reply messages

Implementing queries with the CQRS pattern

Some queries need to retrieve data from multiple services. Since each database is private, the data can only be retrieved using each service’s API. One option is to use API Composition and simply invokes query operations on the services. However, sometimes API composition is inefficient and instead the application must use the CQRS pattern.

The CQRS pattern maintains an easily queryable replica of the data using domain events published by the services that own the data.

How Eventuate solves these distributed data management challenges

Eventuate is a family of frameworks that solve the distributed data management challenges in microservice architecture. By using Eventuate, you can easily implement the Saga and CQRS patterns in your application. Eventuate also provides the messaging primitives for general purpose transactional messaging between services.

The following diagram shows the Eventuate family of frameworks:

There are the following frameworks:

  • Eventuate Tram Sagas - an orchestration-based saga framework
  • Eventuate Tram - a transactional message framework
  • Eventuate Local - an event sourcing framework

Let’s look at the capabilities of these frameworks.

Orchestration-based sagas

The Eventuate Tram Sagas framework implements orchestration-based sagas. It provides an easy to use Java-based domain-specific language for the defining the steps of your saga and their compensating transactions. The saga execution engine is embedded within your services, which simplifies the architecture and improves scalability and availability.

Choreography-based sagas and CQRS

Eventuate makes it easy to implement event-driven microservices that use choreography-based sagas and CQRS. It provides an API for publishing and consuming events. Services can use Eventuate to publish events as part of a database transaction that updates business entity. Other services can use Eventuate to consume events with automatic duplicate detection, which ensures that your message handlers are idempotent.

Eventuate provides different event-driven programming models

  • Explicit event publishing - use for applications that persist business entities using traditional (e.g. JDBC/JPA) persistence. The Eventuate Tram framework provides APIs for publishing and consuming events.
  • Event sourcing - an event-centric way of writing your business logic and persisting your business objects. Event sourcing is useful for application that need to maintain the history of changes to business entities. The Eventuate Local framework is Eventuate’s event sourcing framework.

Foundational messaging patterns

These higher level capabilities are built on several foundational patterns:

  • Transactional Outbox - publish a message as part of the database transaction that updates business entities. This pattern is essential for maintaining consistency. Without it, there is a risk of either updating the database without sending a message or sending a message without the corresponding database update.

  • Idempotent Consumer - detect and discard duplicate messages by tracking the messages that have already been processed. This pattern handles the scenario where a failure causes the message broker to deliver a message more than once.

This patterns are implemented by both the Eventuate Tram and Eventuate Local frameworks.

Learn more

To learn more please take a look at the following resources:

Stay in touch
Copyright © 2021 Eventuate, Inc • All rights reserved.