Konubinix' opinionated web of thoughts

Microservice

Fleeting

Tail the database transaction log and publish each message/event inserted into the outbox to the message broker

https://microservices.io/patterns/data/transaction-log-tailing.html

Relatively obscure although becoming increasing common

https://microservices.io/patterns/data/transaction-log-tailing.html

Tricky to avoid duplicate publishing

https://microservices.io/patterns/data/transaction-log-tailing.html

How to reliably/atomically update the database and publish messages/events?

https://microservices.io/patterns/data/transactional-outbox.html

service that uses a relational database inserts messages/events into an outbox table

https://microservices.io/patterns/data/transactional-outbox.html

service that uses a NoSQL database appends the messages/events to attribute of the record

https://microservices.io/patterns/data/transactional-outbox.html

The service publishes high-level domain events

https://microservices.io/patterns/data/transactional-outbox.html

No 2PC required

https://microservices.io/patterns/data/transactional-outbox.html

The Event sourcing is an alternative solution

https://microservices.io/patterns/data/transactional-outbox.html

From Domain-Driven Design (DDD).

A graph of objects that can be treated as a unit

https://microservices.io/patterns/data/aggregate.html

Organize the business logic of a service as a collection of DDD aggregates that emit domain events when they created or updated. The service publishes these domain events so that they can be consumed by other services

https://microservices.io/patterns/data/domain-event.html

Event sourcing persists the state of a business entity such an Order or a Customer as a sequence of state-changing events. Whenever the state of a business entity changes, a new event is appended to the list of events. Since saving an event is a single operation, it is inherently atomic. The application reconstructs an entity’s current state by replaying the events

https://microservices.io/patterns/data/event-sourcing.html

Applications persist events in an event store, which is a database of events.

https://microservices.io/patterns/data/event-sourcing.html

The store has an API for adding and retrieving an entity’s events. The event store also behaves like a message broker. It provides an API that enables services to subscribe to events. When a service saves an event in the event store, it is delivered to all interested subscribers

https://microservices.io/patterns/data/event-sourcing.html

order to optimize loading, an application can periodically save a snapshot of an entity’s current state. To reconstruct the current state, the application finds the most recent snapshot and the events that have occurred since that snapshot. As a result, there are fewer events to replay

https://microservices.io/patterns/data/event-sourcing.html

solves one of the key problems in implementing an event-driven architecture and makes it possible to reliably publish events whenever state changes

https://microservices.io/patterns/data/event-sourcing.html

Because it persists events rather than domain objects, it mostly avoids the object‑relational impedance mismatch problem

https://microservices.io/patterns/data/event-sourcing.html

100% reliable audit log of the changes made to a business entity

https://microservices.io/patterns/data/event-sourcing.html

different and unfamiliar style of programming and so there is a learning curve.

https://microservices.io/patterns/data/event-sourcing.html

difficult to query since it requires typical queries to reconstruct the state of the business entities. That is likely to be complex and inefficient

https://microservices.io/patterns/data/event-sourcing.html

As a result, the application must use Command Query Responsibility Segregation (CQRS) to implement queries. This in turn means that applications must handle eventually consistent data

https://microservices.io/patterns/data/event-sourcing.html

Define a view database, which is a read-only replica that is designed to support that query. The application keeps the replica up to data by subscribing to Domain events published by the service that own the data.

https://microservices.io/patterns/data/cqrs.html

Supports multiple denormalized views that are scalable and performant

https://microservices.io/patterns/data/cqrs.html

Improved separation of concerns = simpler command and query models

https://microservices.io/patterns/data/cqrs.html

Increased complexity

  • Potential code duplication
  • Replication lag/eventually consistent views

https://microservices.io/patterns/data/cqrs.html

When making a request to a service, the client makes a request via a router (a.k.a load balancer) that runs at a well known location. The router queries a service registry, which might be built into the router, and forwards the request to an available service instance.

https://microservices.io/patterns/server-side-discovery.html

Implement a service registry, which is a database of services, their instances and their locations. Service instances are registered with the service registry on startup and deregistered on shutdown. Client of the service and/or routers query the service registry to find the available instances of a service. A service registry might invoke a service instance’s health check API to verify that it is able to handle requests

https://microservices.io/patterns/service-registry.html

Build your microservices using a microservice chassis framework, which handles cross-cutting concerns

https://microservices.io/patterns/microservice-chassis.html

The major benefit of a microservice chassis is that you can quickly and easy get started with developing a microservice

https://microservices.io/patterns/microservice-chassis.html

When making a request to a service, the client obtains the location of a service instance by querying a Service Registry, which knows the locations of all service instances

https://microservices.io/patterns/client-side-discovery.html

Keep each microservice’s persistent data private to that service and accessible only via its API. A service’s transactions only involve its database

https://microservices.io/patterns/data/database-per-service.html

service’s database is effectively part of the implementation of that service. It cannot be accessed directly by other services

https://microservices.io/patterns/data/database-per-service.html

Without some kind of barrier to enforce encapsulation, developers will always be tempted to bypass a service’s API and access it’s data directly.

https://microservices.io/patterns/data/database-per-service.html

Distributed transactions are best avoided because of the CAP theorem. Moreover, many modern (NoSQL) databases don’t support them.

https://microservices.io/patterns/data/database-per-service.html

There are various patterns/solutions for implementing transactions and queries that span services:

https://microservices.io/patterns/data/database-per-service.html

There are logical components corresponding to different functional areas of the application

https://microservices.io/patterns/microservices.html

team of developers

https://microservices.io/patterns/microservices.html

New team members must quickly become productive

https://microservices.io/patterns/microservices.html

each service is relatively small and so is easier to understand and change

https://microservices.io/patterns/microservices.html

additional complexity

https://microservices.io/patterns/microservices.html

inter-service communication mechanism and deal with partial failure

https://microservices.io/patterns/microservices.html

Implementing requests that span multiple services is more difficult

https://microservices.io/patterns/microservices.html

tangled dependencies might make it difficult to decompose your monolithic application into a set of services.

https://microservices.io/patterns/microservices.html

SRP defines a responsibility of a class as a reason to change, and states that a class should only have one reason to change. It make sense to apply the SRP to service design as well.

https://microservices.io/patterns/microservices.html

loose coupling, each service has its own database.

https://microservices.io/patterns/microservices.html

application must instead use the Saga pattern

https://microservices.io/patterns/microservices.html

service publishes an event when its data changes. Other services consume that event and update their data. There are several ways of reliably updating data and publishing events including Event Sourcing and Transaction Log Tailing

https://microservices.io/patterns/microservices.html

The Database per Service pattern describes how each service has its own database in order to ensure loose coupling

https://microservices.io/patterns/microservices.html

The API Gateway pattern defines how clients access the services in a microservice architecture

https://microservices.io/patterns/microservices.html

Notes linking here