For example, you have a centralized security service. It handles the things related to accounts, profiles and group membership. You have a recipe service. It handles things like finding recipes, adding them to "books", etc. The recipes need to be guarded. They are shown only to members of certain groups.
You could have the recipe service call the security service each time to get the caller's groups. Then compare those groups to the allowed groups. If that user service goes down, you're borked.
If you use events instead, you'd keep a copy of the profile and its groups in the recipes. Every time that changes, it gets an event with the details. Now they've decoupled by sharing data async. It is not a perfect system. It can be possible that the recipes service doesn't update. Now a user that should get the data can't.
The trade off with events is that you can upgrade and redeploy services more easily. If you find a bug in the user profile service, bring it down, update and restart. No other service goes down with it.
All of this makes sense but also seems unavoidable to some degree. Seems like a set of tradeoffs you make by going microservies that you should be weary of.
Having services fully state-decoupled via unified log is interesting. I’ve considered this but it seemed a bit complicated in terms of then being able to scale the services that need, say, local copies of user profiles.
Here's two examples. Provided you don't get much churn in key profile data, you might be able to use JWT to store group membership for example. All services can read the the token. The token provides the groups necessary for the access operation.
Another example is only copying parts of the data. My current project has profiles and memberships. Interestingly the app side code doesn't actually use that information directly. A copy of group membership is held in the DB. When the user executes any operation, the queries themselves check for rights. When a use wants to read a list of recipes, part of the query is "and has read permission". The same is true of updates. The system queries for the resource to update. Only those that the user has an explicit right to modify are found.
That might mean that you still take that cost willingly but engineer in the extra tooling to make things easier to manage – i.e. simplifying tracing load or errors across service boundaries back to the source – but it might also be a cue for you raise to reconsider whether the service divisions are in the right place or whether all of the services are appropriately sized. If you find yourself needed distributed transactions, retries, etc. that’s often a good time to pause and reconsider.
Thank you that makes sense.