Search code examples
microservicesevent-driven-design

Foreign key constraint in mirco-service-oriented architecture


Given the following two microservices, product and shopping-cart, which are connected to an event-bus. Whenever a product gets created, updated or deleted, an event is emitted so that the shopping-cart microservice can update its copies of the product data.

Product and Shopping Cart Mircoservice

Now, how would a business requirement be implemented that no product can be deleted that is still referenced in a users shopping cart.

My thoughts so far:

  • Implement that logic in the product microservice by adding an additional dependency to the shopping-cart microservice. I don´t like that solution, since it increases coupling and introduces a circular dependency.

Any recommended approach or pattern to solve this problem?


Solution

  • I would have the shopping cart service publish an event stream of item added, item removed, cart closed out events. The product service could subscribe directly to these events and track whether the product is in a cart.

    Because there's inherently a lag between an event being published and it being consumed, this does of course bring up the chance that a product gets added to a cart after it was deleted but before the cart service has received the event; the cart service would then publish the cart change events which would reference a deleted item.

    To handle this situation, I would:

    • enforce that carts be closed out after a certain amount of time
    • treat product deletion as pending for at least that period. The deletion event is then a "we intend to delete this product" event which signals the cart service to prevent it from being added but doesn't affect current carts
    • the deletion doesn't take effect until the cart auto-close time has passed since the later of the pending product deletion and the last added-to-cart event for that item

    This does not fully eliminate (e.g. if the cart service is down for longer than the auto-close period) the eventual consistency between the services, but it dramatically reduces the probability. So this leaves two options which are something the business is going to have to decide:

    • They can eliminate the eventual consistency by having a service (could be product, could be cart, could be a new service, could be a merger of product and cart) which would be the coordination point for this. Note that if this service was down (or just inaccessible), it would preclude items from being added to the shopping cart.

    • They can accept a small risk that if the shopping cart service has been down, customers will be able to add items that have been deleted. In this scenario, there's presumably a means to send the customers an apologetic message and some sort of compensation (e.g. a voucher for X off their next purchase).

    Which of these approaches should be taken is purely a business decision; I'd strongly suspect that nearly all businesses would prefer the latter, in view of the likely business impact from losing that coordination service.