We are floating around with the idea of breaking our monolithic application into microservices. The problem we are facing is there are parts of the application the business is not willing to accept the idea of eventual consistency. Our thought is to have a shared database, but each microservice would get its own schema. Microservices will be allowed to read from all schemas but only write to the their own, thus still enforcing some level of bounded context. I've seen some refer to this as a distributed monolith. However scalability is not a concern for us, we don't have a high amount of load / traffic, we need to be able to move faster, and deploy functionality independently.

The App: We have an aging monolithic ERP system. The application handles HR information, insurance information, pay rate, bill rate, timesheet (time tracking), reporting (including payroll), vacation scheduling, clients and projects, employee assignment to projects (all used for the timesheet and invoicing).

The problems:

A: The code base is large, disorganized, and full of legacy code. (Not really a monolith problem, more a result of never refactoring and just shoe horning features in)

B: Long development cycles, and large testing effort.

C: Deployment is an all of nothing situation. If something doesn’t work as intended the entire deployment is rolled back.

At first pass we thought about breaking the system up into the following components:

  • HR (Personal information, Pay Rate, HR notes / incidents, citizenship status, etc)
  • Timesheet (Clients, Projects, Project Assignment, Hours/Timesheets, Bill Rate for project/employee)
  • Reporting Service
  • Vacation Service

The biggest issue we are struggling with moving to a distributed system is dealing with eventually consistency when the business is not willing to accept eventual consistency. Because the system is used for generating payroll and invoicing it needs to be real time. As an example, if Employee A payrate it changed from $20 to $30 an hour, an admin should be able to immediately run a payroll report and it should have the reflect the change.

Another example is the system automatically locks all timesheets and runs payroll at a specific day/time once a week. If someone updated their timesheet 2 min before the lock, but it hadn’t propagated via message bus, or whatever mechanism and payroll reflected older values that would be very bad.

How to design microservices when you need real time consistency without a shared databsae? Would you need to place everything that needs to be consistent within the same microservice / bounded context? I fear that will lead us back to a monolith.

  • 1
    Reading some other microservice's database/schema is not in the spirit of microservices. Instead, one microservice should consult the other microservice by their APIs. That way, one microservice owns its schema, and, it is private, so can be properly interpreted and evolved/refactored as needed. – Erik Eidt Oct 17 at 19:13
  • "the business is not willing to accept [...] eventual consistency" - Comes down to 2 scenarios. Either they are correct (which is certainly a possibility since they are the domain experts) and the particular business process in question really isn't suited for eventual consistency, in which case you have very likely modeled the your bounded contexts wrong (your ideas about what the domain looks like don't line up with the business needs); probably better to model this by a single BC. (Note that the practice is to have a DB per BC, and a BC doesn't necessarily map to a single microservice.) – Filip Milovanović Oct 17 at 21:46
  • The other possibility is that eventual consistency is really acceptable, and your model is solid, but you are getting pushback from decision-makers who happen to have a misconception about this particular issue, in which case you have to convince them (maybe by getting some of their employees, people who make the business process happen, on board). Either way you have to figure this out together with the domain experts. – Filip Milovanović Oct 17 at 21:46
  • @ErikEidt I disagree with "one microservice should consult the other microservice by their APIs". This is no different from reading the other microservice database (it's just a different technology: Rest instead of SQL). By not allowing a service to call another, you are forced to store the data in the right service in the first place. When the data that belongs together is stored together, transactionability problems disappear and eventual consistency appears in places where it is acceptable. Of course, deciding what data goes where becomes quite difficult. – Francesc Castells Oct 30 at 20:19

Since you haven't included a concrete example of a case where an inconsistency could appear, I'll imagine two situations.

First situation

Let's suppose that a service handles employees and another one handles payrolls. If you call the payroll service for a new employee that has yet to be created, you're afraid that the data could become inconsistent: a payroll would be created for a person who doesn't exist yet.

In this case, moving from a monolithic application with a single database to a bunch of services, each owning its data, would not be an issue, because the payroll service could always contact the employees service to ensure that the employee exists. If not, the payroll should not be created.

Of course, you don't have the security mechanism in terms of database constraints. Nevertheless, the similar control can exist at the application level.

Second situation

A service handles payrolls and another one handles insurance information. The payroll service owns a postal address of the person, used to send the payslip. Similarly, the insurance service also has the postal addresses of the employees for its own specific needs. When an address is modified in one of the services, what guarantees that it will also be modified in the other one?

In this case, you'll usually use a third service—such as an employee service—to which two other services will delegate the responsibility of keeping the postal addresses. This way, the information is stored only once, and cannot get inconsistent.

There can be situations which are not that clear. For instance, what if a person is at the same time your employee and your customer? Should you be creating another service to handle the persons in general? Or should you allow some inconsistency (most companies would chose the second solution, which leads to a lot of situations, some funny, some particularly annoying)? There is no right choice for that: it's up to your architect to decide.

Shared database

If you consider those two situations, the shared database brings absolutely no benefit. In both situations, since each of two services is (according to you) not allowed to write to the schema of the other service, there would be no other solutions that to call the other service (first situation) or to have a third service (second situation).

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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