Data Integrity in Distributed Systems In a microservice architecture, you can get dependencies that impose restrictions on the services used. For example, let’s consider that uses the database per service principle: a car rental service owns data about different geographic polygons — cities, and regions. The schema looks like this: Geoareas microservice {id, geometry} , in turn, manages the data of the rental price. Schema looks something like this: . It has a dependence on . Tariffs microservice {id, geoarea_id, price_per_minute} the Geoareas microservice At some point, we need to delete an object from — call the endpoint: the Geoareas microservice DELETE /geoarea?id={id}. This can lead to a number of problems, even including the inaccessibility of the service, since we still have tariffs referencing a removed geoarea. An unpleasant dependence appears: in order to remove a geoarea from you need to make a request to at the time of removal to check which tariff depends on it. (sorry for this) Geoareas Tariffs Dangerous cohesion appears — with this approach, in the future, will send requests to all microservices where geoareas are used. Geoareas By the way, databases have using foreign keys, but in our case, we have a distributed microservice architecture and for that, there are several solutions: automatic integrity control 1. Webhooks The option implies creating a unified webhook mechanism in the microservice. The microservice will execute these hooks before modifying the object. If at least one hook fails, then action on the object is impossible. An example of such a webhook would be a request for a third-party microservice with a predefined API. For our example, the webhook in would look like this: the Geoareas microservice WEBHOOK target=”pre-delete” action=”POST tariffs/check_delete?geoarea_id={id}” In , respectively, you need to implement endpoint to check that the zone can be deleted and that the “is not against”. the Tariffs microservice /check_delete Tariffs microservice The uniformity of these hooks makes them easy to configure on the fly. When a new microservice that uses appears, add a new check to the list of hooks. Geoareas Thus, supports the mechanism of unified webhooks but knows nothing about what kind of business logic is behind these hooks. Geoareas 2. Reference Counting In this option, we will keep an eye on who uses . Geoareas Extending the API of our microservice with these new endpoints: POST /hold?geoarea_id={id}&holder={holder} POST /release?geoarea_id={id}&holder={holder} Thus, if we want to create a new tariff in a zone, then before that we need to block this zone in , for example: the Geoareas microservice POST /hold? geoarea_id=moscow&holder=tariffs_tariffmoscow1 Next to geoareas in , we store a list of those who “hold” these zones. the Geoareas microservice When trying to delete a geoarea, we check the list of holders and do not allow deleting if the list is not empty. If the tariff that holds the geoarea is deleted, then after it is deleted, you need to release the lock, for example: /release?geoarea_id=moscow&holder=tariffs_tariffmoscow1 Also published here.