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.