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:
- A
user_trackers
table is added to microserviceA
. This acts
similar to a join table containing "foreign keys" tousers
andtrackers
. - A
owners
table is added to microserviceB
. 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
- Keep records for
users
andtrackers
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 aregistered user
, with all the information and behavior required for registration? Are you sure it's the right concept for communicating withtrackers
(whatever it is)? So if I got it right, your option 2 is exactly about that: introducing theowner
concept that's much closer to your domain. If it really is so, I'm for option 2 as well.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 andtracker
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.