Let's assume I would like to create a blogging platform that would allow managing user accounts, therefore I came up with 2 microservices:
Blogging- managing posts, tags, etc.Users- managing users, their roles, etc.
It's clear to me that Post contains the ID of the author (User) and User contains IDs of the Posts he wrote.
The problem is that when a client requests a Post, I would also like to return the name of the author and send it together to the client in a DTO (view model). I see 2 possible solutions for that:
- Introduce the concept of the
User(only ID and name) in a domain of theBloggingservice. Every time a client requests aPost, all relevant data is fetched only from this microservice. Every time a user's name is modified in aUsersmicroservice, this service is notified and updated author's names. - Keep the concerns completely separated. Every time a client asks for a
Post,Bloggingmicroservice is called to fetchPostand thenUsersmicroservice is called to fetch the author's name based on the ID.
So far I was leaning towards solution #1 as it would require only 1 call to the 1 microservice when Post is requested, but then let's say if the number of functions (microservices) starts growing and I keep adding small concepts from each of them only to limit the number of calls, I'm afraid I would end up in a spaghetti Blogging microservice... But then I also don't think the number of microservices will grow significantly ;)
Which way do you find better and why? Does any of the approaches break the microservices architecture principles and my concerns are justified?
It really depends on the way your program is going to develop.
Solution #1 (editing the
Bloggingmodel)Here you edit your model for the sake of the performance. Most of the time I don't think altering the model itself for the sake of performance is the right way. If you don't think the concept of an
Userinside theBloggingcontext is right, you shouldn't put it there. Another problem is that you would have to deal with eventual consistency between you bounded contexts (BC). If you think the concept ofUserinsideBloggingis not a bad idea, it might be probably the way to go.Solution #2 (querying the data separately)
Although this might not be performance friendly, I think this would be the easiest way at the beginning. You won't have to deal with eventual consistency (+dealing with synchronizing the data between BC) and you don't have to alter your model. But if you really care about performance and keeping your model clean, you might be interested in read model.
Another solution - read model
The concept of read model is about having at least two separate models: one for reading the data and for writing/editing the data. If we want to implement this concept for your problem, we would create a read model for the
BloggingBC wherePostsandUserscould be merged together (something like in solution #1) and then queried. We can synchronize this data with the help of events, so when thePostorUserchanges, it would raise an event and save the changed data into your read model. This way you can merge/alter any data you want for better performance. It might be very similar to solution #1, but the main difference is that you don't edit your main model. You create new one just for the reading. It is probably the hardest solution, but if your project is large and performance heavy, this might be a way.I wouldn't say any solution is the best or the worst for solving your problem. It always depends on the context.