I'd like some feedback on couple different solutions to handling data dependencies and relations across micro services.
Briefly explained, there is a bank service and an account service. The account service holds the accounts and are always connected to a bank using a bankId.
The dilemma is how to handle and validate this relationship and bankId and the pros and cons that comes with each decision.
Option 1:
Ignore validating completely. POST/PATCH against Accounts will never validate if the given BankId is an existing ID.
Pros
Cons
Reflection
The services are completely decoupled which will benefit performance, up time and complexity. All readers and applications need to be "reactive" and able to handle when cross service relationships are "broken".
Option 2:
Always validate using synchronous REST-call. POST/PATCH against Accounts will fail if BankId does not exist or if in anyway BankService can't respond or is broken.
Pros
Cons
Reflection
Services are tightly dependent which is really bad, this is more like the "old ways" and generally I feel like it's the wrong way to do it. Merging the services in this case is even worse, if you start fixing problems by merging you'd probably keep doing it and soon end up with massive services and you've failed with the whole micro service principle. Sure, reads will still work but that's a far fetched excuse.
Option 3:
Keep a readonly copy of BankEntity in AccountService. AccountService keeps this updated via the event bus. Validate against this on POST/PATCH.
Pros
Cons
Reflection
This is the most complex way, readers won't need to handle broken relationships and the performance / up time-issues are resolved, however, instead you would have to handle the fact that the readonly copy of Banks might not be updated yet and try again later. Comparing this to Option 1 means you'd still have to deal with it in some way, and since this will be more complex across the board I'd say its not the most favourable one.
End Thoughts
The general goal that would be nice to achieve is that the services do not synchronously talk to each other and that data integrity is as good as possible.
However, in a microservice architecture, I'm under the impression that relationship integrity simply might be one of those things you accept to lose going to this way.
Our decision is leaning towards Option 1, actually just ignoring it, and anytime where you need to use it, you have to expect and handle that it might not be correct. This seems like it is the most "microservices" solution, the services don't really know about each other, and the only ones that do are applications and reporting services that need to do cross-service operations.
Any of the services need to take full responsibility that they, at any given time, has all the data they need to fully function themselves. Let's say for arguments sake that AccountEntity NEEDED a location for whatever reason to be a usable and complete domain entity, you can't expect to rely on BankId, you'd have to store Location on AccountEntity and maybe if it changes, you'd get an event and you can update it.
TL;DR What are your experiences, opinions, and thoughts on this? What would you do? Which strategy would you go for?
First of all the option that you choose will depend on your business needs.
** First i would allow account to be created without the validation, the initial state of the account is CREATED
** Now in AccountService create a ProcessManager which listen to AccountCreated Event and in async validates it with Bank Service to check whether Bank Id is valid, if yes , update the account state to VERIFIED , or if invalid bank id , update the state to INVALID BANK ID and take the appropriate action
Now actually all approach are valid, might depends on your critical business needs.Sometimes real time validation is required even if it creates a dependency