Microservices – Use case for shared database

microservices

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.

Best Answer

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).

Related Topic