Microservices – Managing Many-to-Many Associations

microservices

I currently have two microservices. We'll call them A and B.

The database under microservice A has the following table:

A
|-- users

The database under microservice B has the following table:

B
|-- trackers

The requirements state that users and trackers have a many-to-many relationship.

I'm not sure how to properly handle this within a microservices architecture.

I could see this working one of three ways:

  1. A user_trackers table is added to microservice A. This acts
    similar to a join table containing "foreign keys" to users and trackers.
  2. A owners table is added to microservice B. This table acts similar
    to a polymorphic join table. This would allow any service to create an
    association with a tracker. This may look somewhat like this:

    B
    |-- trackers
    |-- owners
    |-- owner_id
    |-- owner_type
    |-- tracker_id
  3. Keep records for users and trackers in each microservice. Keep them in sync with some sort of pubsub system.

I was originally going to go with option 2 because I liked that it preserved transaction boundaries. I can create a tracker and associate it with something atomically. However, it seems out of scope for microservice B. Why should microservice B care that microservice A wants to create an association?

I feel like there's probably a good pattern here that I'm not aware of. Do any of the options I laid out make sense? Is there another option that may make more sense?

Best Answer

First of all, I'd start with domain description. You haven't mentioned what it is about (I can guess, but it'd be only a guess). After that I would try to decompose it using value-chain analysis or business-capability mapping. And only after that I would think about implementation.

Considering your problem, the first thing that goes to my mind is that you identified your service boundaries wrong, simply because they need each other's data. You don't want to end up with distributed monolith, do you?

The second thing is that you probably haven't worked through your domain good enough. What concept is represented with users table? Is it a registered user, with all the information and behavior required for registration? Are you sure it's the right concept for communicating with trackers (whatever it is)? So if I got it right, your option 2 is exactly about that: introducing the owner concept that's much closer to your domain. If it really is so, I'm for option 2 as well.

However, it seems out of scope for microservice B. Why should microservice B care that microservice A wants to create an association?

It's all about boundaries. I guess you want to form microservices around entities. That's where SOA failed with its layered service architecture. The better approach is to create services that represent some business function, so they encapsulate both data and behavior. From more practical point of view, it's about creating services around business-processes or use-cases. For example, you could have one service for user registration. It contains user's data and behavior required to register a user. Thus the concept of user is formed naturally, and it belongs only to service A. And this brings me to the next point: the other way to think about services is bounded context. It's a good practice to align services and bounded contexts.

When user is registered, UserCreated event could be emitted. Your second service I guess is interested in it. So upon receiving it a completely different entity could be created, say, Owner entity (whatever that is, either). I.m pretty sure there are a lot of interesting collaborations between it and tracker entity -- keep them in a single service.

Be extremely cautious with option 3. If you copy data, functionality follows. It results in tight coupling. And don't cover with CQRS term, it's not about data synchronization between services via events.

Related Topic