4

We are trying to develop a microservices based application. The idea is to come up with a good pattern and would ideally like to develop it so that each service is loosely coupled with its own database. But how would we handle data that is common across multiple services.

Let's consider an example of country and state information required across multiple services.

We came up with a few options here:

  1. Replicate the tables in each service, with a country management service separately for managing country data, and each other service subscribing for any updates (but here the data is replicated across multiple services)
  2. A Common database for country data (but that could potentially become a single point of failure)
  3. Single country management service and other services accessing the country data through this

Which one would be the ideal choice to implement this? Or is there a better way of handling this scenario.

  • 1
    Not everything needs to be a microservice. Some things just don't fit into that pattern. – Jon Raynor Aug 15 at 12:50
  • 1
    the correct answer is 3. Why the confusion? – Ewan Aug 15 at 13:44
  • @JonRaynor The idea is to develop the application in a microservice architecture, with strict Domain Driven Design (even if most of the microservice can be simply written as a basic API service). Please don't ask why. – roshan Aug 16 at 1:41
  • @Ewan Again the question of single point of failure, frequent requests to this service. We are trying to develop every service in a strict DDD pattern, and in that case, there might probably be a sort of tight coupling with this country service, which we think violates DDD principles. Not 100% sure. – roshan Aug 16 at 1:43
5

Data is not a service. Access to data may be a service. Processing data definitely is. You should ask yourself: what does my system do with that data? What is the service interface that my domain components require to access in order to use the country data? And then:

  • Do all my components agree on the syntax of that interface?
  • Do all my components agree on a particular implementation of that interface? Most trivial example: if your interface offers country name resolution, does every component agree that the country with the numerical ISO code 840 is spelled "United States of America", or do some components require "USA"?
  • Do all my components agree on the semantics of that interface? When countries 278 and 280 merge to form 276, do all your components agree with that? Or do some ignore 276 and require all former 278 addresses to be listed in 280 now?
  • Do all my components agree on the lifecycle of the underlying data? For example, does the name resolution represent the current name, subject to change when country 807 changes its name from "F.Y.R.M." to "North Macedonia" or do some disagree, because "addresses are free text anyway, so don't mess with them"

There are more questions like that, and they all boil down to: Are your countries true entities, or do they exist mostly in the imagination of all the components of your system?

The more questions you answer with yes, the more you should lean towards 3, the more questions you answer with no, the more you should lean towards 1.

4

1 or 3 depending on the data and your needs. A shared database is a no-no since it then means your services are not independently deployable and scalable. You need one service that owns the data and is its source of truth. It can then make sense to also replicate the data to cut down on latency if that is more important than the data being up to date.

1

3 is the correct option with microservices.

The idea is for each microservice to protect and own its data. This keeps it consistent and allows you to restrict the impact of code changes as well as all the other microservice goodness.

You are avoid the single point of failure with various standard High Availability techniques.

This design should work well with DDD as a shared service like this maps to a DDD domain service, ie where you need to access info from a separate domain to make a decision.

It might be easier to go over the problems with solutions 1 and 2

  1. the simplest solution a shared database which every service connects to.

    Obviously the problem here is that you probably have business logic updating or otherwise using this data. You could put it all in sprocs, but then you have effectively created a micro service with a SQL interface

  2. Microservice for updates, replication to local databases for reads.

    The problem here is that you could well have business logic on read as well as write. Caching the results of calls, or subscribing to updates from a service instead of replicating the DB can help with that, but again, you then have a microservice. You have just fiddled with the messaging protocol.

    Also, if you are pushing updates you still need an initial status pull

0

As it seems the County entity can't be a rich model of your business. Using DDD alongside CQRS would solve your basic question of responsiblity sergration.

In you Core service (country is an entity of this domain) write your command which can mutate the state of this bounded context. Other services can query the needed data from this service effortlessly.

In the case that you need to mutate Country's state from other services, you just need to send a Command through your event bus (you cant't call a simple api to change the data in Core service).

In this scenario your services are loosed coupled, because the Core service is the only service that can mutate it's bounded context's state. Using technologies like High Availiblity or Caching (redis front of your database) you can be sure of the stability and resiliency of your services.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.