Search code examples
spring-bootdesign-patternsarchitecturemicroservices

Writing code that run across different regions


I am working on enhancing a Spring boot Microservice that is developed for the Consumer registration in the UK region. The service domain model and validation logic is coded based on the consumer registration details in UK. The Micro service accepts UI to provide Consumer's name, address etc and run some validation on that before registering consumer with system.

I have to enhance this service to run for the US region. The existing domain model won't fit for the US. In UK, consumer's address format is different than US. Also, there is no SSN in the UK region. There are different address verification systems in UK vs US.

So overall, I cannot use the same Micro service developed for US region. I wanted to ask, how do we develop Services that works across different geographies considering differences in the domain model and requirement for integration with different back-end systems (address validation for example).


Solution

  • It depends how deep the domain model goes. If the domain model is only something that exists at the microservice level then changes at the microservice level will fix it, but, if the domain model goes all the way down into the core systems then changes at the microservice level will only be a band-aid at best.

    The problem is not just how data is processed but also how it is stored in the backend / core systems.

    When planning changes to accommodate the US, it might be worth asking if how likely it is that other geographies might be added later. It's not that you want to start over-engineering things straight away (YAGNI, etc) but at the same time it might help you choose options that mean you don't paint yourself into a corner.

    To answer your actual question:

    ...how do we develop Services that works across different geographies considering differences in the domain model and requirement for integration with different back-end systems (address validation for example).

    Here a couple of options. There are variations on these but hopefully they'll give you a good start:

    enter image description here

    Option A (Left): Logic in Single Microservice

    Assumes that the UI (or whatever is calling the microservice) has determined what region is needed. In the microservice:

    • Implement a system based on the Dependency Inversion Principle (DIP) so that something in the microservice (called Logic Loader in the diagram) can load up the correct regions logic.
    • Write separate logic for each region. The challenge here is to figure out how & where you'll deal with the inconsistencies between regions. Usually with DIP implementations you might have an interface that providers (the region logic's) must implement. E.g. SaveDwellingNumber(int streetNumber, int level, int apartmentNumber) But as hopefully as you can see straightaway, strongly typed method signatures are not going to be possible / easy.
    • Use a further module to sort out any differences in the data so that the data coming out of the microservice is consistent regardless of region - this assumes your backend core system only has one way of storing addresses.

    Depending on how the UI works, one of the functions the region logic system handles might be to tell the UI which region-specific input fields to display.

    This solution feels a bit dirty, but it would allow you to deal with different regions whilst providing a uniform set of output data to a backend system that only had one way of understanding an address.

    Option B (Right): Layered Microservices

    This works on the same principles as the other option, but a different implementation.

    • Experience API (could be an API on an API Gateway or a microservice) - is what UIs (callers) talk to. It's job is to provide a single consistent API for callers, and to route / orchestrate calls to the appropriate microservice.
    • UK / US Region Microservices - do the region specific heavy lifting.
    • Core System Microservice, performs the role that the consistency / mapper does in option A. This microservice is also a good place to put in protections for the core system, such as caching if it's performance is poor.

    Comparison

    Option B allows you to separate concerns more easily, e.g. if your business said 'actually we might look at adding Cambodia and Latvia next year', then this approach is probably going to give you more options down the road, because there's only so much you can reasonably squeeze into a single microservice. You can also deploy instances of relevant microservices into *aaS platforms geo-regions that make sense.

    If you figure out your logic and functional skeleton using option A, you could re-build that out to option B later. Option A is a smaller & simpler implementation so faster to build initially, but hard to say how long it would last.

    Option B is more compartmentalized, so easier to have multiple people/teams working on different parts of it.

    Finally, as long as this answer is, it doesn't really address the challenges inherent in the different data and what logic you need, but it does talk about how you can approach the microservices that such logic sits in.