Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Microservices: how to handle foreign key relationships

People also ask

How do you handle relationships in microservices?

In your case, you prefer to use database per service pattern. This make microservices more autonomous. In this situation, you should duplicate some of your data among multiple microservices. You can share the data with api calls between microservices or you can share it with async messaging.

How do microservices communicate with each other internally?

Because microservices are distributed and microservices communicate with each other by inter-service communication on network level. Each microservice has its own instance and process. Therefore, services must interact using an inter-service communication protocols like HTTP, gRPC or message brokers AMQP protocol.

Can 2 microservices connect to same database?

Yes, it's possible to integrate a database for microservices. You can create a single shared database with each service accessing data using local ACID transactions.

How can 2 microservices share common models between each other?

The whole point of microservices is that they can change and scale independently. Sharing those models will force those services to iterate together, and will enforce strong coupling (bad). To deal with shared domains in a microservice architecture, keep you binding to a minimum.


It is possible to use a shared database for multiple microservices. You can find the patterns for data management of microservices in this link: http://microservices.io/patterns/data/database-per-service.html. By the way, it is a very useful blog for microservices architecture.

In your case, you prefer to use database per service pattern. This make microservices more autonomous. In this situation, you should duplicate some of your data among multiple microservices. You can share the data with api calls between microservices or you can share it with async messaging. It depends on your infrastructure and frequency of change of the data. If it is not changing often, you should duplicate the data with async events.

In your example, Delivery service can duplicate delivery locations and product information. Product service manage the products and locations. Then the required data is copied to Delivery service's database with async messages (for example you can use rabbit mq or apache kafka). Delivery service does not change the product and location data but it uses the data when it is doing its job. If the part of the product data which is used by Delivery service is changing often, data duplication with async messaging will be very costly. In this case you should make api calls between Product and Delivery service. Delivery service asks Product service to check whether a product is deliverable to a specific location or not. Delivery service asks Products service with an identifier (name, id etc.) of a product and location. These identifiers can be taken from end user or it is shared between microservices. Because the databases of microservices are different here, we cannot define foreign keys between the data of these microservices.

Api calls maybe easier to implement but network cost is higher in this option. Also your services are less autonomous when you are doing api calls. Because, in your example when Product service is down, Delivery service cannot do its job. If you duplicate the data with async messaging, the required data to make delivery is located in the database of Delivery microservice. When Product service is not working you will be able to make delivery.


When distributing your code to achieve reduced coupling, you want to avoid resource sharing, and data is a resource you want to to avoid sharing.

Another point is that only one component in your system owns the data (for state changing operations), other components can READ but NOT WRITE, they can have copies of the data or you can share a view model they can use to get the latest state of an object.

Introducing referential integrity will reintroduce coupling, instead you want to use something like Guids for your primary keys, they will be created by the creator of the object, the rest is all about managing eventual consistency.

Take a look at Udi Dahan's talk in NDC Oslo for a more details

Hope this helps


first solution: API Composition

 Implement a query by defining an API Composer, which invoking the
 services that own the data and performs an in-memory join of the
 results

enter image description here

second solution: CQRS

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.

enter image description here